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 *array@len

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

(gdb) p *array@len
$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  fg 三個命令都是一樣的意思。


step <count>
單步跟蹤,如果有函數調用,他會進入該函數。進入函數的前提是,此函數被編譯有 debug 信息。很像 VC 等工具中的step in 。後面可以加 count 也可以不加,不加表示一條條地執行,加表示執行後面的 count 條指令,然後再停住。

next <count>
同樣單步跟蹤,如果有函數調用,他不會進入該函數。很像 VC 等工具中的 step over 。後面可以加 count 也可以不加,不加表示一條條地執行,加表示執行後面的 count 條指令,然後再停住。

set step-mode
set step-mode on
打開 step-mode 模式,於是,在進行單步跟蹤時,程序不會因爲沒有 debug 信息而不停住。這個參數有很利於查看機器碼。

set step-mod off
關閉 step-mode 模式。

finish
運行程序,直到當前函數完成返回。並打印函數返回時的堆棧地址和返回值及參數值等信息。

until  u
當你厭倦了在一個循環體內單步跟蹤時,這個命令可以運行程序直到退出循環體。

stepi  si
nexti 
 ni
單步跟蹤一條機器指令!一條程序代碼有可能由數條機器指令完成, stepi  nexti 可以單步執行機器指令。與之一樣有相同功能的命令是 “ display/i $pc ” ,當運行完這個命令後,單步跟蹤會在打出程序代碼的同時打出機器指令(也就是彙編代碼)


設置觀察點( WatchPoint  

觀察點一般來觀察某個表達式(變量也是一種表達式)的值是否有變化了,如果有變化,馬上停住程序。我們有下面的幾種方法來設置觀察點: 

watch <expr>
爲表達式(變量) expr 設置一個觀察點。一量表達式值有變化時,馬上停住程序。 

rwatch <expr>
當表達式(變量) expr 被讀時,停住程序。 

awatch <expr>
當表達式(變量)的值被讀或被寫時,停住程序。 

info watchpoints
列出當前所設置了的所有觀察點。

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章