我在main()
内调用main()
,递归10次。现在在使用gdb
(bt / backtrace)进行调试时,我看不到main()
的多个帧。为什么呢?
#include<stdio.h>
int main(){
static int i;
int num=100;
if(i>10)
return 0;
else {
i++;
num++;
main();
printf("\n%d",num);
}
}
答案 0 :(得分:4)
这是gdb
及is (supposed to be) configurable的记录行为。
当我使用gcc 4.7.2
(-O3
)编译代码时,我得到以下程序集:
_main:
LFB1:
movl _i.2134(%rip), %eax
cmpl $10, %eax
jle L6
xorl %eax, %eax
ret
L6:
addl $1, %eax
pushq %rdx
LCFI0:
movl %eax, _i.2134(%rip)
xorl %eax, %eax
call _main ; <=== recursive call
popq %rcx
LCFI1:
movl $101, %esi
xorl %eax, %eax
leaq LC0(%rip), %rdi
jmp _printf
LFE1:
这驳斥了递归调用被优化掉的假设。
现在,如果我将二进制文件加载到gdb
并在main()
上设置断点,则会反复命中。当我检查寄存器时,%rsp
每次调用都会递减,因此每个main()
都有明显的堆栈帧。
尽管如此,bt
只显示一个框架:
(gdb) bt
#0 0x0000000100000f50 in main ()
(在这种情况下,我知道有三个main()
帧,而不仅仅是一个。)
因此,我得出结论,这与gdb
本身有关。
经过进一步调查,结果表明此行为为documented:
大多数程序都有一个标准的用户入口点 - 系统库和启动代码转换为用户代码的地方。对于C,这是
main
。当gdb
在回溯中找到入口函数时,它将终止回溯,以避免跟踪到高度系统特定的(通常是无趣的)代码。
当我在gdb
中设置以下内容时:
set backtrace past-main on
set backtrace past-entry on
它开始显示两个main()
帧。出于某种原因,它仍然没有更深入。
答案 1 :(得分:2)
您的问题与您使用main
无关。
一个简单的递归程序,你最终可以在注释中向我们展示,编译器可以很容易地通过不进行递归来优化它。在你的情况下,它通常更简单,因为你有一个预定义的递归深度10
。这可以很容易地由编译器展开到静态代码。
答案 2 :(得分:1)
Here is the Answer for my own Question.
(gdb) set backtrace past-main on
(gdb) b main
Breakpoint 1 at 0x4004b0: file recursion.c, line 5.
(gdb) run
Starting program: /nobackup/arjprasa/C/gdb/a.out
Breakpoint 1, main () at recursion.c:5
5 int num=100;
(gdb) c
Continuing.
Breakpoint 1, main () at recursion.c:5
5 int num=100;
(gdb) bt
#0 main () at recursion.c:5
#1 0x00000000004004df in main () at recursion.c:12
#2 0x00000034d091c4cb in __libc_start_main () from /lib64/tls/libc.so.6
#3 0x000000000040041a in _start ()
(gdb) c
Continuing.
Breakpoint 1, main () at recursion.c:5
5 int num=100;
(gdb) bt
#0 main () at recursion.c:5
#1 0x00000000004004df in main () at recursion.c:12
#2 0x00000000004004df in main () at recursion.c:12
#3 0x00000034d091c4cb in __libc_start_main () from /lib64/tls/libc.so.6
#4 0x000000000040041a in _start ()
(gdb) c
Continuing.
Breakpoint 1, main () at recursion.c:5
5 int num=100;
(gdb) bt
#0 main () at recursion.c:5
#1 0x00000000004004df in main () at recursion.c:12
#2 0x00000000004004df in main () at recursion.c:12
#3 0x00000000004004df in main () at recursion.c:12
#4 0x00000034d091c4cb in __libc_start_main () from /lib64/tls/libc.so.6
#5 0x000000000040041a in _start ()
(gdb)