2016-11-07 694 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,我能夠成功查看堆棧跟蹤。 –

相關問題