2016-11-07 68 views
3

我正在尝试使用GDB排查我正在编写的代码中的段错误。当我使用backtrace命令时,GDB不显示行号或函数名称。下面是说明我的问题很短的示例程序:为什么GDB不显示行号或函数名称?

void segfault(int *b) { 
    // This causes a segfault on CentOS7 Intel 64-bit 
    b[-1] = 5; 
} 

void main() { 
    int a[10]; 
    segfault(a); 
} 

然而,当我与

gcc -ggdb -O0 test.c -o segfaulttest 

编译和使用gdb segfaulttest来运行它,当我使用gdb的回溯命令我没有得到任何行号或功能名称。我期望它在跟踪中列出main()segfault()

样本输出

Reading symbols from /home/user/test/segfaulttest...done. 
(gdb) run 
Starting program: /home/user/test/segfaulttest 

Program received signal SIGSEGV, Segmentation fault. 
0x000000050040051c in ??() 
(gdb) bt 
#0 0x000000050040051c in ??() 
#1 0x0000000000000000 in ??() 
(gdb) 

我使用:

  • CentOS的7(64位)
  • GCC:gcc (GCC) 4.8.5 20150623 (Red Hat 4.8.5-4)
  • GDB是gcc (GCC) 4.8.5 20150623 (Red Hat 4.8.5-4)

(除了:我修正了实际情况错误在我的代码中,我只是不明白为什么gdb backtrace没有显示更多信息)。

回答

5

您已经销毁了包含gdb需要知道程序所在位置的信息的堆栈部分。

0x000000050040051c in ??() 
    ^^^^^^^^ 

这是你的代码写的数字5,一个4字节的int。

当main()启动时,返回地址存储在堆栈上。返回地址 是main()在完成时返回的位置。这个地方是一个函数,它是调用main()的运行时的一部分。

由于返回地址被代码破坏/覆盖,执行尝试跳回到某个不存在的地址,导致崩溃。

该地址0x000000050040051c现在是程序计数器寄存器,它在SIGSEGV信号传送到您的进程时被存储。 gdb检查此信息,试图找出与地址0x000000050040051c匹配的代码位于何处 - 哪些不存在。

+0

感谢您的快速,可以理解的答案。我尝试将segfault()更改为:void segfault(){raise(SIGSEGV); }'并再次运行gdb,我能够成功查看堆栈跟踪。 –

相关问题