首页
学习
活动
专区
圈层
工具
发布
社区首页 >问答首页 >启用尾优化时反向跟踪可能不正确的原因

启用尾优化时反向跟踪可能不正确的原因
EN

Stack Overflow用户
提问于 2021-02-26 03:38:22
回答 1查看 109关注 0票数 1

https://www.gnu.org/software/libc/manual/html_node/Backtraces.html

注意,某些编译器优化可能会干扰获得有效的回溯。函数内联导致内联函数没有堆栈帧;尾调用优化将一个堆栈帧替换为另一个堆栈帧;帧指针消除将阻止反向跟踪正确解释堆栈内容。

我想知道为什么在启用尾优化时应该发生这种情况,以及如何避免它。

EN

回答 1

Stack Overflow用户

回答已采纳

发布于 2021-02-26 06:06:23

我想知道在启用尾部优化时为什么会发生这种情况

这将发生在尾调用优化中,因为在编译器使用它之后,递归函数将不是递归函数,或者调用堆栈中将完全缺少尾递归函数。

示例:

代码语言:javascript
复制
// t.c
int foo() { return 42; }
int bar() { return foo(); }
int main() { return bar(); }

gcc -O2 -fno-inline t.c && gdb -q ./a.out

(gdb) b foo
Breakpoint 1 at 0x1140
(gdb) run
Starting program: /tmp/a.out

Breakpoint 1, 0x0000555555555140 in foo ()
(gdb) bt
#0  0x0000555555555140 in foo ()
#1  0x00007ffff7dfad0a in __libc_start_main (main=0x555555555040 <main>, argc=1, argv=0x7fffffffdc08, init=<optimized out>, fini=<optimized out>, rtld_fini=<optimized out>, stack_end=0x7fffffffdbf8) at ../csu/libc-start.c:308
#2  0x000055555555507a in _start ()

main()bar()去了哪里?我们知道main()肯定还在堆栈上。

它们是经过优化的尾部呼叫:

代码语言:javascript
复制
(gdb) disas main
Dump of assembler code for function main:
   0x0000555555555040 <+0>:     xor    %eax,%eax
   0x0000555555555042 <+2>:     jmpq   0x555555555150 <bar>
End of assembler dump.
(gdb) disas bar
Dump of assembler code for function bar:
   0x0000555555555150 <+0>:     xor    %eax,%eax
   0x0000555555555152 <+2>:     jmp    0x555555555140 <foo>
End of assembler dump.

如何避免它。

避免这种情况的唯一方法是禁用尾调用优化(使用-fno-optimize-sibling-calls):

代码语言:javascript
复制
gcc -O2 -fno-inline t.c -fno-optimize-sibling-calls && gdb -q ./a.out

(gdb) b foo
Breakpoint 1 at 0x1140
(gdb) run
Starting program: /tmp/a.out

Breakpoint 1, 0x0000555555555140 in foo ()
(gdb) bt
#0  0x0000555555555140 in foo ()
#1  0x0000555555555157 in bar ()
#2  0x0000555555555047 in main ()
票数 1
EN
页面原文内容由Stack Overflow提供。腾讯云小微IT领域专用引擎提供翻译支持
原文链接:

https://stackoverflow.com/questions/66379780

复制
相关文章

相似问题

领券
问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档