main()以递归方式调用main() - gdb backtrace不显示多个main()帧 - 为什么?

时间:2012-12-19 09:54:47

标签: c gdb

我在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); 
     }
 }

3 个答案:

答案 0 :(得分:4)

这是gdbis (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)