1. 程式人生 > >GDB除錯總結和例項

GDB除錯總結和例項

1)啟動gdb

gdb hello

或者

gdb
file hello

2)顯示程式

list 或者 l

3)打斷點

break(b) main()   //函式的入口處
break(b) 11       //行號
break(b) hello.c:14 //特定檔案的行號
break(b) 12 if i=10 //if語句滿足後在行號處打斷點

4)獲取斷點資訊

info break

5)刪除斷點

delete 13(斷點編號)

6)執行程式

run(r)

7)單步(不進入子函式)

next(n)

8)單步(進入子函式)

step(s)

9)繼續執行

continue(c)

10)檢視變數

print(p) i(變數名)

11)執行程式到當前函式結束

finish

12)監控變數

watch i(變數名)

13)退出gdb

quit(q)

一:列檔案清單
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 個整數,一個動態陣列的語法如下所示:

[email protected]
因此,要想顯示在 h 後面的 10 個元素,可以使用 [email protected]
(gdb)print [email protected]
$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
----------------------------------------------

#include <stdio.h>

static char buff [256];
static char* string;

int main ()
{
    printf ("Please input a string: ");
    gets (string);
    printf ("\nYour string is: %s \n", string);
}

上面這個程式非常簡單,其目的是接受使用者的輸入,然後將使用者的輸入打印出來。該程
序使用了一個未經過初始化的字串地址 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.然後繼續執行,將看到正確的程式執行結果。