1. 程式人生 > >gdb用法(一)基本gdb命令

gdb用法(一)基本gdb命令

GDB 概述 
GDB是GNU開源組織釋出的一個強大的UNIX下的程式除錯工具。或許,各位比較喜歡那種影象介面方式的,像VC、BCB等IDE的除錯,但如果你是在UNIX平臺下做軟體,你會發現GDB這個除錯工具有比VC、BCB的影象化偵錯程式更強大的功能。所謂“寸有所長,尺有所短”就是這個道理。
一般來說,GDB主要幫忙你完成下面四個方面的功能:
1、啟動你的程式,能按照你的自定義的需求隨心所欲的執行程式。
2、可讓被除錯的程式在你所指定的調置的斷點處停住。(斷點能是條件表示式)
3、當程式被停住時,能檢查此時你的程式中所發生的事。
4、動態的改動你程式的執行環境。

使用GDB

一般來說GDB主要除錯的是C/C++的程式。要除錯C/C++的程式,首先在編譯時,我們必須要把除錯資訊加到可執行檔案中。使用編譯器(cc/gcc/g++)的 -g 引數能做到這一點。如:
> gcc -g hello.c -o hello
> g++ -g hello.cpp -o hello
如果沒有-g,你將看不見程式的函式名、變數名,所代替的全是執行時的記憶體地址。當你用-g把除錯資訊加入之後,併成功編譯目的碼以後,讓我們來看看怎麼用gdb來除錯他。

啟動GDB的方法有以下幾種: 
1、gdb program 
program 也就是你的執行檔案,一般在當前目錄下。
2、gdb program core 
用gdb同時除錯一個執行程式和core檔案,core是程式非法執行後core dump後產生的檔案。
3、gdb program 1234 
如果你的程式是個服務程式,那麼你能指定這個服務程式執行時的程序ID。gdb會自動attach上去,並除錯他。program應該在PATH環境變數中搜索得到。

基本 gdb 命令.

命 令 描 述 
file 裝入想要除錯的可執行檔案. 
kill 終止正在除錯的程式. 
list 列出產生執行檔案的原始碼的一部分. 


next 執行一行原始碼但不進入函式內部. 
step 執行一行原始碼而且進入函式內部. 
run 執行當前被除錯的程式 
quit 終止 gdb 
watch 使你能監視一個變數的值而不管它何時被改變. 
break 在程式碼裡設定斷點, 這將使程式執行到這裡時被掛起. 
make 使你能不退出 gdb 就可以重新產生可執行檔案. 
shell 使你能不離開 gdb 就執行 UNIX shell 命令.

利用print 命令可以檢查各個變數的值。

whatis 命令可以顯示某個變數的型別

從斷點繼續執行:countinue 命令

顯示當前gdb的斷點資訊: info break

刪除指定的某個斷點: delete breakpoint 1

禁止使用某個斷點 disable breakpoint 1

允許使用某個斷點 enable breakpoint 1

gdb除錯程式的方法

1)進入gdb除錯:
 gdb + 已經編譯通過的可執行程式 -》 就進入除錯模式。例如:gdb MiddlePublisher
2)r + 執行時的引數 -》 開始執行可執行程式。例如 r -lxml2 -f refile 
3)b + 斷點 -》設定除錯的斷點。兩種:一種是:b CMSTask.cpp:200 表示在CMSTask.cpp檔案的第200行設定斷點 。

另一種:b TaskManager::buildPubWinTask 表示在執行buildPubWinTask這個函式的時候停止。 
4)取消斷點:
  dis 1 表示取消第一個斷點 
  dis 2 表示取消第二個斷點 
5)檢視設定斷點資訊: info b 
6)在斷點停止處檢視所在程式碼的詳細資訊:l 
7)可以在gdb中直接編譯,然後再重新執行時,gdb會直接執行新編譯好的可執行程式。例如:直接在gdb下執行make後再重慶執行。 
8)跟進一個函式:s 
  如果設定的斷點是在一個函式入口。到達該斷點時,鍵入s就可以進入該函式內部進行除錯。如果有多個函式就多次鍵入S來進入內部的函式。

小結:常用的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 顯示變數或函式型別

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  “ @ ”操作符, “ @ ” 的左邊是第一個記憶體的地址的值, “ @ ” 的右邊則你你想檢視記憶體的長度。例如,你的程式中有這樣的語句: 

int *array = (int *) malloc (len * sizeof (int));

於是,在 GDB 除錯過程中,你可以以如下命令顯示出這個動態陣列的取值:

p *[email protected]

的左邊是陣列的首地址的值,也就是變數 array 所指向的內容,右邊則是資料的長度,其儲存在變數 len 中,其輸出結果,大約是下面這個樣子的: 

(gdb) p *[email protected]
$1 = {2, 4, 6, 8, 10, 12, 14, 16, 18, 20, 22, 24, 26, 28, 30, 32, 34, 36, 38, 40}

如果是靜態陣列的話,可以直接用 print 陣列名,就可以顯示陣列中所有資料的內容了。

檢視棧資訊 
—————

當程式被停住了,你需要做的第一件事就是檢視程式是在哪裡停住的。當你的程式呼叫了一個函式,函式的地址,函式引數,函式內的區域性變數都會被壓入 “  ”  Stack )中。你可以用 GDB 命令來檢視當前的棧中的資訊。

下面是一些檢視函式呼叫棧資訊的 GDB 命令:

backtrace
bt
列印當前的函式呼叫棧的所有資訊。如: 

(gdb) bt
#0 func (n=250) at tst.c:6
#1 0x08048524 in main (argc=1, argv=0xbffff674) at tst.c:30
#2 0x400409ed in __libc_start_main () from /lib/libc.so.6

從上可以看出函式的呼叫棧資訊: __libc_start_main --> main() --> func()

backtrace <n>
bt <n>
是一個正整數,表示只打印棧頂上 層的棧資訊。

backtrace <-n>
bt <-n>
-n 
表一個負整數,表示只打印棧底下 層的棧資訊。 如果你要檢視某一層的資訊,你需要在切換當前的棧,一般來說,程式停止時,最頂層的棧就是當前棧,如果你要檢視棧下面層的詳細資訊,首先要做的是切換當前棧。

frame <n>
f <n>
是一個從 開始的整數,是棧中的層編號。比如: frame 0 ,表示棧頂, frame 1 ,表示棧的第二層。 

up <n>
表示向棧的上面移動 層,可以不打 ,表示向上移動一層。 

down <n>
表示向棧的下面移動 層,可以不打 ,表示向下移動一層。 

上面的命令,都會打印出移動到的棧層的資訊。如果你不想讓其打出資訊。你可以使用這三個命令: 

select-frame <n> 
對應於 frame 命令。 
up-silently <n> 
對應於 up 命令。 
down-silently <n> 
對應於 down 命令。

檢視當前棧層的資訊,你可以用以下 GDB 命令:

frame  f
會打印出這些資訊:棧的層編號,當前的函式名,函式引數值,函式所在檔案及行號,函式執行到的語句。 

info frame
info f
這個命令會打印出更為詳細的當前棧層的資訊,只不過,大多數都是執行時的內內地址。比如:函式地址,呼叫函式的地址,被呼叫函式的地址,目前的函式是由什麼樣的程式語言寫成的、函式引數地址及值、區域性變數的地址等等。如: 
(gdb) info f
Stack level 0, frame at 0xbffff5d4:
eip = 0x804845d in func (tst.c:6); saved eip 0x8048524
called by frame at 0xbffff60c
source language c.
Arglist at 0xbffff5d4, args: n=250
Locals at 0xbffff5d4, Previous frame's sp is 0x0
Saved registers:
ebp at 0xbffff5d4, eip at 0xbffff5d8

info args
打印出當前函式的引數名及其值。 

info locals
打印出當前函式中所有區域性變數及其值。 

info catch
打印出當前的函式中的異常處理資訊。

恢復程式執行和單步除錯

當程式被停住了,你可以用 continue 命令恢復程式的執行直到程式結束,或下一個斷點到來。也可以使用 step next 命令單步跟蹤程式。

continue [ignore-count]
c [ignore-count]
fg [ignore-count]
恢復程式執行,直到程式結束,或是下一個斷點到來。 ignore-count 表示忽略其後的斷點次數。 continue