gdb的使用(二) 堆棧跟蹤、core文件、連接到其它進程

堆棧跟蹤

程序“調用堆棧”是當前函數之前的所有已調用函數的列表(包括當前函數)。每個函數及其變量都被分配了一個“幀”,最近調用的函數在 0 號幀中(“底部”幀)。

backtrace / bt:要打印堆棧,發出命令 'bt'('backtrace' [回溯] 的縮寫)。在顯示幀信息的最後的行號表示了被調用的函數所在行,可以用list+行號的方式查看

例如:
------------------------------------------------------------------------
(gdb) bt
#0 0x80483ea in wib (no1=8, no2=8) at eg1.c:7
#1 0x8048435 in main (argc=1, argv=0xbffff9c4) at eg1.c:21
------------------------------------------------------------------------

此結果顯示了在 main() 的第 21 行中調用了函數 wib()(只要使用 'list 21' 就能證實這一點),而且 wib() 在 0 號幀中,main() 在 1 號幀中。由於 wib() 在 0 號幀中,那麼它就是執行程序時發生算術錯誤的函數。
實際上,發出 'info locals' 命令時,gdb 會打印出當前幀中的局部變量,缺省情況下,這個幀中的函數就是被中斷的函數(0 號幀)。可以使用命令 'frame' 打印當前幀。要查看 main 函數(在 1 號幀中)中的變量,可以發出 'frame 1' 切換到 1 號幀,然後發出 'info locals' 命令查看

frame:打印當前幀信息,'frame 幀號'切換到相應的幀。用法見上例。

up, down:可以通過如上所示在 'frame' 命令中明確指定號碼,或者使用 'up' 命令在堆棧中上移以及 'down' 命令在堆棧中下移來切換幀。要獲取有關幀的進一步信息,如它的地址和程序語言,可以使用命令 'info frame'

core 文件

無法dump core文件的原因:

使用 ulimit -c 查看shell對core文件的限制,單位爲塊(512b)。如果爲0,則表示系統關閉了dump core。可以通過ulimit -c unlimited來打開。

若發生了段錯誤,但沒有core dump,是由於系統禁止core文件的生成!
$ulimit -c,若顯示爲0,則系統禁止了core dump

解決方法:
$ulimit -c unlimited(只對當前shell進程有效)
或在~/.bashrc的最後加入: ulimit -c unlimited (一勞永逸)

加載core文件:要使用 core 文件啓動 gdb,在 shell 中發出命令 'gdb eg1 core' 或 'gdb eg1 -c core'。

加載後,可以發出 'info locals'、'print'、'info args' 和 'list' 命令來查看調試信息。'info variables' 命令將打印出所有程序變量的值,但這要進行很長時間,因爲 gdb 將打印 C 庫和程序代碼中的變量。爲了更容易地查明在調用 wib() 的函數中發生了什麼情況,可以使用 gdb 的堆棧命令。

gdb連接到其它進程

除了調試 core 文件或程序之外,gdb 還可以連接到已經運行的進程(它的程序已經過編譯,並加入了調試信息),並中斷該進程。只需用希望 gdb 連接的進程標識替換 core 文件名就可以執行此操作。

以下是一個執行循環並睡眠的 示例程序: 

eg2 示例代碼
------------------------------------------------------------------------
#include 
int main(int argc, char *argv[])
{
int i;
for(i = 0; i < 60; i++)
{
sleep(1);
}
return 0;
}
------------------------------------------------------------------------
使用 'gcc -g eg2.c -o eg2' 編譯該程序並使用 './eg2 &' 運行該程序。請留意在啓動該程序時在背景上打印的進程標識,在本例中是 1283:
------------------------------------------------------------------------
./eg2 &
[3] 1283
------------------------------------------------------------------------

連接到進程:'gdb 被調試文件 -c 進程號' 也可以不要 -c。
啓動 gdb 並指定進程標識,在我舉的這個例子中是 'gdb eg2 1283'。gdb 會查找一個叫作 "1283" 的 core 文件。如果沒有找到,那麼只要進程 1283 正在運行(在本例中可能在 sleep() 中),gdb 就會連接並中斷該進程:
------------------------------------------------------------------------
...
/home/seager/gdb/1283: No such file or directory.
Attaching to program: /home/seager/gdb/eg2, Pid 1283
...
0x400a87f1 in __libc_nanosleep () from /lib/libc.so.6
(gdb)
------------------------------------------------------------------------
此時,可以發出所有常用 gdb 命令。可以使用 'backtrace' 來查看當前位置與 main() 的相對關係,以及 mian() 的幀號是什麼,然後切換到 main() 所在的幀,查看已經在 "for" 循環中運行了多少次:
------------------------------------------------------------------------
(gdb) backtrace
#0 0x400a87f1 in __libc_nanosleep () from /lib/libc.so.6
#1 0x400a877d in __sleep (seconds=1) at ../sysdeps/unix/sysv/linux/sleep.c:78
#2 0x80483ef in main (argc=1, argv=0xbffff9c4) at eg2.c:7
(gdb) frame 2
#2 0x80483ef in main (argc=1, argv=0xbffff9c4) at eg2.c:7
7 sleep(1);
(gdb) print i
$1 = 50
------------------------------------------------------------------------
detach / kill:輸入'detach' or 'kill',不需要進程號。
如果已經完成了對程序的修改,可以 'detach' 命令繼續執行程序,或者 'kill' 命令殺死進程。
attach:先輸入'file eg2',然後輸入'attach 1283'
還可以首先使用 'file eg2' 裝入文件,然後發出 'attach 1283' 命令連接到進程標識 1283 下的 eg2。

其它小技巧
shell:
輸入'shell'可以打開一個新的shell,或使用'shell [commandline]'在當前的shell中運行命令。
gdb 可以讓您通過使用 shell 命令在不退出調試環境的情況下運行 shell 命令,調用形式是 'shell [commandline]',這有助於在調試時更改源代碼。

set:命令修改變量的值,'set 變量=值'
最後,在程序運行時,可以使用 'set ' 命令修改變量的值。在 gdb 下再次運行 eg1,使用命令 'break 7 if diff==0' 在第 7 行(將在此處計算結果)設置條件斷點,然後運行程序。當 gdb 中斷執行時,可以將 "diff" 設置成非零值,使程序繼續運行直至結束:
------------------------------------------------------------------------
Breakpoint 1, wib (no1=8, no2=8) at eg1.c:7
7 result = no1 / diff;
(gdb) print diff
$1 = 0
(gdb) set diff=1
(gdb) continue
Continuing.
0 wibed by 16 equals 10
Program exited normally.
------------------------------------------------------------------------

 原文地址 http://hi.baidu.com/andrewhome/blog
發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章