c++ c optimization compiler-optimization tail-call-optimization

c++ - ¿Por qué el código intentaría activamente evitar la optimización de la llamada final?



optimization compiler-optimization (3)

Esto es solo una suposición, pero tal vez para evitar un bucle infinito vs bombardeo con un error de desbordamiento de pila.

Dado que el método en cuestión no pone nada en la pila, parece posible que la optimización de la recursión de la cola produzca un código que entraría en un bucle infinito en lugar del código no optimizado que pondría la dirección de retorno en la pila que finalmente se desbordaría en caso de mal uso.

La única otra idea que tengo está relacionada con la preservación de las llamadas en la pila para la depuración y la impresión de seguimiento de la pila.

El título de la pregunta puede ser un poco extraño, pero la cuestión es que, hasta donde yo sé, no hay nada que contradiga en absoluto la optimización de las llamadas finales. Sin embargo, mientras navegaba por proyectos de código abierto, ya encontré algunas funciones que intentan activamente evitar que el compilador haga una optimización de la cola de llamadas, por ejemplo, la implementación de CFRunLoopRef que está lleno de tales ataques . Por ejemplo:

static void __CFRUNLOOP_IS_CALLING_OUT_TO_AN_OBSERVER_CALLBACK_FUNCTION__() __attribute__((noinline)); static void __CFRUNLOOP_IS_CALLING_OUT_TO_AN_OBSERVER_CALLBACK_FUNCTION__(CFRunLoopObserverCallBack func, CFRunLoopObserverRef observer, CFRunLoopActivity activity, void *info) { if (func) { func(observer, activity, info); } getpid(); // thwart tail-call optimization }

Me encantaría saber por qué esto parece ser tan importante, y ¿hay algún caso en el que yo, como desarrollador normal, debería mantener esto también en cuenta? P.ej. ¿Hay trampas comunes con la optimización de llamadas de cola?


Mi suposición aquí es que es para asegurar que __CFRUNLOOP_IS_CALLING_OUT_TO_AN_OBSERVER_CALLBACK_FUNCTION__ esté en el seguimiento de la pila para la depuración. Tiene __attribute__((no inline)) que respalda esta idea.

Si se da cuenta, esa función simplemente funciona y rebota en otra función de todos modos, por lo que es una forma de trampolín que solo creo que está ahí con un nombre tan detallado para ayudar a la depuración. Esto sería especialmente útil dado que la función llama a un puntero de función que se ha registrado desde otro lugar y, por lo tanto, esa función puede no tener acceso a símbolos de depuración.

Observe también las otras funciones con nombres similares que hacen cosas similares: realmente parece que está ahí para ayudar a ver lo que sucedió en una traza inversa. Tenga en cuenta que este es el código principal de Mac OS X y se mostrará en los informes de fallas y también procesará los informes de muestra.


Una posible razón es facilitar la depuración y la creación de perfiles (con TCO, el marco de pila padre desaparece, lo que hace que los rastros de pila sean más difíciles de entender).