GDB調試精粹及使用執行個體
來源:不詳 (2006-07-14 11:18:05)
一:列檔案清單
1. List
(gdb) list line1,line2
二:執行程式
要想運行準備調試的程式,可使用run命令,在它後面可以跟隨發給該程式的任何參數,包括標準輸入和標準輸出說明符(<和>)和外殼萬用字元(*、?、[、])在內。
如果你使用不帶參數的run命令,gdb就再次使用你給予前一條run命令的參數,這是很有用的。
利用set args 命令就可以修改發送給程式的參數,而使用show args 命令就可以查看其預設參數的列表。
(gdb)set args –b –x
(gdb) show args
backtrace命令為堆棧提供向後跟蹤功能。
Backtrace 命令產生一張列表,包含著從最近的過程開始的所以有效流程和調用這些過程的參數。
三:顯示資料
利用print 命令可以檢查各個變數的值。
(gdb) print p (p為變數名)
whatis 命令可以顯示某個變數的類型
(gdb) whatis p
type = int *
print 是gdb的一個功能很強的命令,利用它可以顯示被調試的語言中任何有效運算式。運算式除了包含你程式中的變數外,還可以包含以下內容:
l 對程式中函數的調用
(gdb) print find_entry(1,0)
l 資料結構和其他複雜物件
(gdb) print *table_start
$8={e=reference=’\000’,location=0x0,next=0x0}
l 值的曆史成分
(gdb)print $1 ($1為記錄變數,在以後可以直接引用 $1 的值)
l 人為數組
人為數組提供了一種去顯示儲存空間塊(數組節或動態分配的儲存區)內容的方法。早期的偵錯工具沒有很好的方法將任意的指標換成一個數組。就像對待參數一樣,讓我們查看記憶體中在變數h後面的10個整數,一個動態數組的文法如下所示:
base@length
因此,要想顯示在h後面的10個元素,可以使用h@10:
(gdb)print h@10
$13=(-1,345,23,-234,0,0,0,98,345,10)
四:斷點(breakpoint)
break命令(可以簡寫為b)可以用來在調試的程式中設定斷點,該命令有如下四種形式:
l break line-number 使程式恰好在執行給定行之前停止。
l break function-name 使程式恰好在進入指定的函數之前停止。
l break line-or-function if condition 如果condition(條件)是真,程式到達指定行或函數時停止。
l break routine-name 在指定常式的入口處設定斷點
如果該程式是由很多原檔案構成的,你可以在各個原檔案中設定斷點,而不是在當前的原檔案中設定斷點,其方法如下:
(gdb) break filename:line-number
(gdb) break filename:function-name
要想設定一個條件斷點,可以利用break if命令,如下所示:
(gdb) break line-or-function if expr
例:
(gdb) break 46 if testsize==100
從斷點繼續運行:countinue 命令
五.斷點的管理
1. 顯示當前gdb的斷點資訊:
(gdb) info break
他會以如下的形式顯示所有的斷點資訊:
Num Type Disp Enb Address What
1 breakpoint keep y 0x000028bc in init_random at qsort2.c:155
2 breakpoint keep y 0x0000291c in init_organ at qsort2.c:168
(gdb)
2.刪除指定的某個斷點:
(gdb) delete breakpoint 1
該命令將會刪除編號為1的斷點,如果不帶編號參數,將刪除所有的斷點
(gdb) delete breakpoint
3.禁止使用某個斷點
(gdb) disable breakpoint 1
該命令將禁止斷點 1,同時斷點資訊的 (Enb)域將變為 n
4.允許使用某個斷點
(gdb) enable breakpoint 1
該命令將允許斷點 1,同時斷點資訊的 (Enb)域將變為 y
5.清除原檔案中某一程式碼上的所有斷點
(gdb)clean number
註:number 為原檔案的某個程式碼的行號
六.變數的檢查和賦值
l whatis:識別數組或變數的類型
l ptype:比whatis的功能更強,他可以提供一個結構的定義
l set variable:將值賦予變數
l print 除了顯示一個變數的值外,還可以用來賦值
七.逐步執行
l next
不進入的逐步執行
l step
進入的逐步執行
如果已經進入了某函數,而想退出該函數返回到它的調用函數中,可使用命令finish
八.函數的調用
l call name 調用和執行一個函數
(gdb) call gen_and_sork( 1234,1,0 )
(gdb) call printf(“abcd”)
$1=4
l finish 結束執行當前函數,顯示其傳回值(如果有的話)
九.機器語言工具
有一組專用的gdb變數可以用來檢查和修改電腦的通用寄存器,gdb提供了目前每一台電腦中實際使用的4個寄存器的標準名字:
l $pc : 程式計數器
l $fp : 幀指標(當前堆疊框架)
l $sp : 棧指標
l $ps : 處理器狀態
十.訊號
gdb通常可以捕捉到發送給它的大多數訊號,通過捕捉訊號,它就可決定對於正在啟動並執行進程要做些什麼工作。例如,按CTRL-C將中斷訊號發送給gdb,通常就會終止gdb。但是你或許不想中斷gdb,真正的目的是要中斷gdb正在啟動並執行程式,因此,gdb要抓住該訊號並停止它正在啟動並執行程式,這樣就可以執行某些調試操作。
Handle命令可控制訊號的處理,他有兩個參數,一個是訊號名,另一個是接受到訊號時該作什麼。幾種可能的參數是:
l nostop 接收到訊號時,不要將它發送給程式,也不要停止程式。
l stop 接受到訊號時停止程式的執行,從而允許程式調試;顯示一條表示已接受到訊號的訊息(禁止使用訊息除外)
l print 接受到訊號時顯示一條訊息
l noprint 接受到訊號時不要顯示訊息(而且隱含著不停止程式運行)
l pass 將訊號發送給程式,從而允許你的程式去處理它、停止運行或採取別的動作。
l nopass 停止程式運行,但不要將訊號發送給程式。
例如,假定你截獲SIGPIPE訊號,以防止正在調試的程式接受到該訊號,而且只要該訊號一到達,就要求該程式停止,並通知你。要完成這一任務,可利用如下命令:
(gdb) handle SIGPIPE stop print
請注意,UNIX的訊號名總是採用大寫字母!你可以用訊號編號替代訊號名
如果你的程式要執行任何訊號處理操作,就需要能夠測試其訊號處理常式,為此,就需要一種能將訊號發送給程式的簡便方法,這就是signal命令的任務。該 命令的參數是一個數字或者一個名字,如SIGINT。假定你的程式已將一個專用的SIGINT(鍵盤輸入,或CTRL-C;訊號2)訊號處理常式設定成采 取某個清理動作,要想測試該訊號處理常式,你可以設定一個斷點並使用如下命令:
(gdb) signal 2
continuing with signal SIGINT(2)
該程式繼續執行,但是立即傳輸該訊號,而且處理常式開始運行.
十一. 原檔案的搜尋
search text:該命令可顯示在當前檔案中包含text串的下一行。
Reverse-search text:該命令可以顯示包含text 的前一行。
十二.UNIX介面
shell 命令可啟動UNIX外殼,CTRL-D退出外殼,返回到 gdb.
十三.命令的曆史
為了允許使用曆史命令,可使用 set history expansion on 命令
(gdb) set history expansion on
小結:常用的gdb命令
backtrace 顯示程式中的當前位置和表示如何到達當前位置的棧跟蹤(同義字:where)
breakpoint 在程式中設定一個斷點
cd 改變當前工作目錄
clear 刪除剛才停止處的斷點
commands 命中斷點時,列出將要執行的命令
continue 從斷點開始繼續執行
delete 刪除一個斷點或監測點;也可與其他命令一起使用
display 程式停止時顯示變數和表達時
down 下移棧幀,使得另一個函數成為當前函數
frame 選擇下一條continue命令的幀
info 顯示與該程式有關的各種資訊
jump 在來源程式中的另一點開始運行
kill 異常終止在gdb 控制下啟動並執行程式
list 列出相應於正在執行的程式的原檔案內容
next 執行下一個來源程式行,從而執行其整體中的一個函數
print 顯示變數或運算式的值
pwd 顯示當前工作目錄
pype 顯示一個資料結構(如一個結構或C++類)的內容
quit 退出gdb
reverse-search 在源檔案中反向搜尋正規運算式
run 執行該程式
search 在源檔案中搜尋正規運算式
set variable 給變數賦值
signal 將一個訊號發送到正在啟動並執行進程
step 執行下一個來源程式行,必要時進入下一個函數
undisplay display命令的反命令,不要顯示運算式
until 結束當前迴圈
up 上移棧幀,使另一函數成為當前函數
watch 在程式中設定一個監測點(即資料斷點)
whatis 顯示變數或函數類型
****************************************************
GNU的調試器稱為gdb,該程式是一個互動式工具,工作在字元模式。在 X Window 系統中,有一個gdb的前端圖形工具,稱為xxgdb。gdb 是功能強大的偵錯工具,可完成如下的調試任務:
* 設定斷點;
* 監視程式變數的值;
* 程式的逐步執行;
* 修改變數的值。
在可以使用 gdb 偵錯工具之前,必須使用 -g 選項編譯源檔案。可在 makefile 中如下定義 CFLAGS 變數:
CFLAGS = -g
運行 gdb 偵錯工具時通常使用如下的命令:
gdb progname
在 gdb 提示符處鍵入help,將列出命令的分類,主要的分類有:
* aliases:命令別名
* breakpoints:斷點定義;
* data:資料查看;
* files:指定並查看檔案;
* internals:維護命令;
* running:程式執行;
* stack:調用棧查看;
* statu:狀態查看;
* tracepoints:跟蹤程式執行。
鍵入 help 後跟命令的分類名,可獲得該類命令的詳細清單。
gdb 的常用命令
命令 解釋
break NUM 在指定的行上設定斷點。
bt 顯示所有的調用棧幀。該命令可用來顯示函數的調用順序。
clear 刪除設定在特定源檔案、特定行上的斷點。其用法為clear FILENAME:NUM
continue 繼續執行正在調試的程式。該命令用在程式由於處理訊號或斷點而 導致停止運行時。
display EXPR 每次程式停止後顯示運算式的值。運算式由程式定義的變數組成。
file FILE 裝載指定的可執行檔進行調試。
help NAME 顯示指定命令的協助資訊。
info break 顯示當前斷點清單,包括到達斷點處的次數等。
info files 顯示被調試檔案的詳細資料。
info func 顯示所有的函數名稱。
info local 顯示當函數中的局部變數資訊。
info prog 顯示被偵錯工具的執行狀態。
info var 顯示所有的全域和靜態變數名稱。
kill 終止正被調試的程式。
list 顯示原始碼段。
make 在不退出 gdb 的情況下運行 make 工具。
next 在不逐步執行進入其他函數的情況下,向前執行一行原始碼。
print EXPR 顯示運算式 EXPR 的值。
******gdb 使用範例************************
-----------------
清單 一個有錯誤的 C 來源程式 bugging.c
代碼:
-----------------
1 #i nclude
2
3 static char buff [256];
4 static char* string;
5 int main ()
6 {
7 printf ("Please input a string: ");
8 gets (string);
9 printf ("\nYour string is: %s\n", string);
10 }
-----------------
上面這個程式非常簡單,其目的是接受使用者的輸入,然後將使用者的輸入列印出來。該程式使用了一個未經過初始化的字串地址 string,因此,編譯並運行之後,將出現 Segment Fault 錯誤:
$ gcc -o bugging -g bugging.c
$ ./bugging
Please input a string: asfd
Segmentation fault (core dumped)
為了尋找該程式中出現的問題,我們利用 gdb,並按如下的步驟進行:
1.運行 gdb bugging 命令,裝入 bugging 可執行檔;
2.執行裝入的 bugging 命令 run;
3.使用 where 命令查看程式出錯的地方;
4.利用 list 命令查看調用 gets 函數附近的代碼;
5.唯一能夠導致 gets 函數出錯的因素就是變數 string。用print命令查看 string 的值;
6.在 gdb 中,我們可以直接修改變數的值,只要將 string 取一個合法的指標值就可以了,為此,我們在第8行處設定斷點 break 8;
7.程式重新運行到第 8行處停止,這時,我們可以用 set variable 命令修改 string 的取值;
8.然後繼續運行,將看到正確的程式運行結果。