为什么代码会主动尝试阻止尾部呼叫优化?
这个问题的标题可能有点奇怪,但事实是,就我所知,根本就没有什么能说明跟尾部优化有关。 然而,在浏览开源项目时,我已经遇到了一些主动尝试阻止编译器进行尾部调用优化的函数,例如CFRunLoopRef的实现,它充满了这样的黑客攻击 。 例如:
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 }
我很想知道为什么这看起来如此重要,是否有任何情况下我作为一个正常的开发人员应该保持这种心态呢? 例如。 尾部呼叫优化有常见的缺陷吗?
这只是一个猜测,但也许可以避免一个无限循环与爆炸堆栈溢出错误。
由于所讨论的方法并没有将任何东西放在堆栈上,所以尾部调用recursion优化看起来可能产生将进入无限循环的代码,而不是非优化的代码,这会将返回地址放在堆栈上如果发生误用,最终会溢出。
我唯一的想法是保留堆栈调用和堆栈跟踪打印。
我的猜测是确保__CFRUNLOOP_IS_CALLING_OUT_TO_AN_OBSERVER_CALLBACK_FUNCTION__
在堆栈跟踪中用于debugging目的。 它有__attribute__((no inline))
,这支持这个想法。
如果你注意到,那个函数就会跳到另一个函数,所以这是一种蹦床的forms,我只能认为这是一个绰号,以帮助debugging。 这是特别有用的,因为该函数正在调用已从别处注册的函数指针,因此该函数可能不具有可访问的debugging符号。
还要注意其他类似命名的function,它们做类似的事情 – 它看起来像是在那里帮助看到从追踪发生了什么。 请记住,这是核心的Mac OS X代码,也将显示在崩溃报告和stream程示例报告中。
一个潜在的原因是使debugging和分析更容易(使用TCO时,父堆栈框架消失,这使堆栈跟踪难以理解)。