歡迎來到Linux教程網
Linux教程網
Linux教程網
Linux教程網
您现在的位置: Linux教程網 >> UnixLinux >  >> Linux基礎 >> 關於Linux

Linux下使用GDB詳解

一、GDB的靜態調試啟動方法:

1、當需要在命令行通過gdb來啟動可執行程序的時候,可使用一下命令:

gdb <可執行程序名>

這個時候gdb會加載可執行程序的符號表和堆棧,並為啟動程序作好准備;

接下來,需要設置可執行程序的命令行參數:

set args <參數列表>

然後設置斷點: b或break;

最後通過命令r或run來啟動程序,或者通過c或continue命令來繼續已經被暫停的程序;

2、當程序core的時候,需要查看core文件的內容,顆使用以下方式:

gdb <可執行程序名> <core文件名>

這個時候,gdb會結合可執行程序的符號和堆棧來查看core文件內容,以分析程序在core掉時的內存影象;

二、GDB的動態調試啟動方法:

動態調試就是在不終止正在運行的進程的情況下來對這個正在運行的進程進行調試;其啟動方式有兩種:

方式一:

gdb <可執行程序名> <進程ID>

比如: gdb <可執行程序名> 1234

這條命令會把進程ID為1234的進程與gdb聯系起來,也就是說,這條命令會把進程ID為1234的進程的地址空間附著在gdb的地址空間中,然後使這個進程在gdb的環境下運行,這樣的話,gdb就可以清楚地了解該進程的執行情況、函數堆棧、內存使用情況,等等;

方式二:

直接在gdb中把一個正在運行的進程連接到gdb中,以便於進行動態調試;使用attach命令:

attach  <進程ID>

當使用attach命令時,你應該先使用file命令來指定進程所聯系的程序源代碼和符號表;當gdb接到attach命令後的第一件事情就是停止進程的運行,你可以使用所有gdb的命令來調試一個已"連接"到gdb的進程,這就像你使用run/r命令在gdb中啟動它一樣.如果你要進程繼續運行,那麼,可以使用continue/c命令就可以了;

detach:

當你調試結束之後,可以使用該命令斷開進程與gdb的連接(結束gdb對進程的控制),在這個命令執行之後,你所調試的那個進程將繼續運行;

如果你在使用attach命令把一個正在運行的進程連接到gdb之後又退出了gdb,或者是使用run/r命令執行了另外一個進程,那麼剛才那個被連接到gdb的進程將會因為收到一個kill命令而退出;

如果要使用attach命令,你的操作系統環境就必須支持進程;另外,你還需要有向進程發送信號的權力;

使用attach命令的例子:

gdb

file <可執行程序名>   #指定進程所關聯的程序源代碼和符號表

attach <進程ID>

.....

使用gdb的命令進行調試;

.....

detach     #調試結束,解除進程與gdb的連接,使進程繼續運行;

三、GDB調試過程中使用到的概念和命令

1、gdb的工作路徑:

在gdb命令提示符下:

pwd: 查看gdb當前的工作路徑;

cd : 改變gdb當前的工作路徑;

info terminal:顯示gdb當前所使用的終端的類型信息;

2、gdb的環境

在gdb命令提示符下:

show paths: 顯示當前路徑變量的設置情況;

show environment/env [VARNAME]:顯示程序的環境變量VARNAME的值;如果不指明環境變量名,那麼該命令將顯示所有環境變量的值;

set environment/env VARNAME [=] VALUE:設置程序的某個環境變量VARNAME的值;不過,只對你所調試的程序有效,對gdb本身不起作用;

unset environment/env VARNAME:刪除程序的某個環境變量VARNAME;

3、程序的停止和繼續

調試器的基本功能就是讓你能夠在程序運行時在終止之前在某些條件成立的時候停下來,然後你就可以使用gdb的所有命令來檢查程序變量的值和修改變量的值,這樣的話,你就可以檢查當的你程序出錯時你的程序究竟做了什麼.

當程序停止的時候,gdb都會顯示一些有關程序狀態的信息,比如:程序停止的原因、堆棧,等等.如果要了解更詳細的信息,可以使用info program命令來顯示當前程序運行的狀態信息;

 info program: 顯示有關你的程序的狀態信息,你的程序是在運行還是停止,是什麼進程,為什麼停止,等等;

4、斷點:

斷點的作用是當你的程序運行到斷點時,無論它在做什麼,都會被停止下來.對於每個斷點,你還可以設置一些更高級的信息以決定斷點在什麼時候起作用.

設置斷點的位置:代碼行、函數上、地址上.在那些含有異常處理的語言(如C++)中,還可以在異常發生的地方設置斷點;

斷點分為普通斷點和條件斷點;

5、設置普通的斷點:

使用break/b命令來設置普通斷點;有很多種方法可以設置斷點:

A、break FUNCTION

在某個函數上設置斷點.當使用允許函數重載的語言(如:C++)時,有可能同時在幾個重載的函數上設置了斷點;

比如:CLogManager類有三個重載的成員函數insert(const struct log_mo_simple&)、insert(const struct log_mt_simple&)、insert(const struct log_st_simple&)

設置斷點: break CLogManager::insert

執行該命令之後,gdb會找到實現CLogManager類的源文件,然後在這三個重載的成員函數上都設置一個斷點;

B、break +OFFSET 或 break -OFFSET

程序運行到當前行時的前幾行或後幾行; OFFSET表示行號;

C、break LINENUM

在行號為LINENUM的行上設置斷點.程序在運行到次行之前會自動被gdb停止;

D、break FILENAME:LINENUM

在文件名為FILENAME的源文件中的第LINENUM行上設置斷點;

E、break FILENAME:FUNCTION

在文件名為FILENAME的源文件中的名為FUNCTION的函數上設置斷點;

F、break *ADDRESS

在地址ADDRESS上設置斷點.這個命令允許你在沒有調試信息的程序中設置斷點;

G、break

不含任何參數的break命令,會在當前執行到的程序運行棧中的下一條指令上設置一個斷點.除了棧底以外,這個命令使程序在一旦從當前函數返回時停止;相似的命令是finish,但是finish命令並不設置斷點.這一點在循環語句中很有用;gdb在恢復執行時,至少要執行一條命令;

6、條件斷點:

條件斷點就是設置的斷點只在某個條件成立的時候才有效,才會使程序在運行到斷點之前停止;語法:

break ... if CONDITION

這個命令設置一個條件斷點,條件由CONDITION來決定.在gdb每次執行到此時,如果CONDITION條件的值被計算為非0,那麼程序就在該斷點處停止;

tbreak ARGS:

該命令設置斷點為只有效一次.ARGS的使用同"break"中的參數的使用;

7、刪除斷點:

當一個斷點使用完之後,需要刪除這些斷點;clear命令和delete命令可以完成這項任務;

A、clear:

不帶任何參數的clear命令會在當前所選擇的棧上清除下一個所要執行到的斷點(指令級).當你當前的棧幀是棧中最內層的時候,使用這個命令可以很方便地刪除剛才程序停止處的斷點;

B、clear FUNCTION 和 clear FILENAME:FUNCTION

刪除名為FUNCTION的函數上的斷點;

C、clear LINENUM 和 clear FILENAME:LINENUM

刪除第LINENUM行上的斷點;

D、delete [breakpoints] [BNUMS...]

刪除參數所指定的斷點,如果沒有指定參數,則刪除程序中所有的斷點.這個命令可以縮寫成d;

8、使斷點暫時不起作用:

使用enable命令來激活斷點或觀察點,使用disable命令來使斷點或觀察點暫時不起作用,使用info break或info watch命令來觀察哪些斷點是活躍的;

斷點或觀察點有四種狀態:

A、使能:

當程序運行到斷點處的時候,程序自動停止.使用break命令設置的斷點默認情況下都是使能的;

B、不使能:

斷點雖然被設置了,但是它不影響程序的運行,程序不會在斷點處停止;

C、使能一次後變為不使能:

斷點對程序運行的影響只有一次,然後就自動變為不使能狀態了.使用tbreak命令設置的斷點默認是這個狀態的;

D、使能一次之後自動刪除:

斷點在起了一次作用之後被自動刪除了;

使用一下命令來使能或不使能斷點:

A、disable [breakpoints] [BNUMS...]

使參數所指定的斷點或觀察點變為不使能狀態;如果沒有指定參數,那麼缺省的動作就是使程序中設置的所有斷點和觀察點都變為不使能狀態;當一個斷點或觀察點被使能之後,它在不使能前的狀態會被記錄下來,在斷點或觀察點再次被激活的時候,原來的狀態會得到繼續.該命令縮寫為dis;

B、enable [breakpoints] [BNUMS...]

使能參數所指定的斷點或全部斷點;

C、enable [breakpoints] once BNUMS...

使能參數所指定的斷點或全部斷點,但是這些斷點都只被使能這些斷點一次;

D、enable [breakpoints] delete BNUMS...

使能參數所指定的斷點或全部斷點,但是這些斷點在被使能一次之後就被自動刪除了;

除了使用tbreak命令設置的斷點之外,其余的命令所設置的斷點在被設置時都是使能的;

9、查看斷點或觀察點的狀態信息:

A、info breakpoints [BREAKNUM]

查看斷點號BREAKNUM所指定的斷點的狀態信息;如果沒有指定參數,則查看所有斷點的狀態信息;

B、info break [BREAKNUM]

查看斷點號BREAKNUM所指定的斷點的狀態信息;如果沒有指定參數,則查看所有斷點的狀態信息;

C、info watchpoints [BREAKNUM]

查看斷點號BREAKNUM所指定的觀察點的狀態信息;如果沒有指定參數,則查看所有觀察點的狀態信息;

D、maint info breakpoints

與info breakpoints一樣,顯示所有斷點的狀態信息,不論是你設置的還是gdb自動設置的;

10、設置觀察點:

可以使用一個觀察點來停止一個程序的執行,當某個表達式的值改變時,觀察點將會停止程序,而不需要事先在某個地方設置一個斷點;由於觀察點的這個特性,使觀察點的開銷比較大,但是再捕捉錯誤時非常有用,特別別是當你不知道程序到底在什麼地方出了問題;

A、watch EXPR

watch命令使用EXPR作為表達式設置一個觀察點.gdb將把表達式加入到程序中,並監視程序的運行,當表達式的值被改變的時候,gdb將會停止程序;

B、rwatch EXPR:

使用EXPR作為表達式設置一個斷點,當EXPR被程序讀取時,程序被gdb暫停;

C、awatch EXPR:

使用EXPR作為表達式設置一個觀察點,當EXPR被讀出然後被寫入時,gdb會暫停程序;這個命令常和rwatch合用;

D、info watchpoints:

顯示所有設置的觀察點的列表;它與info breakpoints命令類似;

11、其它gdb調試命令:

A、list/l [LINE_NUM]:

顯示源文件中行號為LINE_NUM的前面幾行到後面幾行之間的源代碼;如果不執行行號,則顯示當前行的前面幾行到後面幾行之間的源代碼;

B、continue/c: 繼續運行被中斷的程序;

C、next/n: 繼續執行下一行代碼;

D、step/s: 單步跟蹤調試,它可以進入函數內部,跟蹤函數的內部執行情況;

E、backtrace/bt: 顯示當前堆棧的內容;

F、print/p <表達式/變量>: 打印表達式或變量的值;

G、frame/f <STACK_FRAME_NO/ADDRESS>: 選擇一個棧幀,並進入這個棧幀,同時打印被選擇的棧幀的內容摘要信息;該命令的參數是一個棧幀的號碼或者是一個棧幀地址;

H、info stack/frame: 顯示棧/幀的摘要信息;

I、run/r: 在gdb中啟動並運行程序;

J、help info: 顯示命令info的用法;

K、help <Command>: 顯示命令Command的詳細用法;

L、注意gdb的幫助系統help的使用,通過它,可以獲得更多的使用信息;

12、對多線程程序的調試:

A、thread THREAD_NO: 該命令用於在線程之間進行切換,把線程號為THREAD_NO(gdb設置的線程號)的線程設置為當前線程;

B、info threads: 查詢當前進程所擁有的所有線程的狀態摘要信息;gdb按照順序顯示:

a、線程號: gdb為被調試進程中的線程設置的順序號;

b、目標系統的線程標識;

3、此線程的當前棧信息;

一些前面帶'*'號的線程,表示該線程是當前線程;

C、thread apply [THREAD_NO] [ALL] ARGS: 該命令用於向線程提供命令;

另外,無論gdb何時中斷了你的程序(因為一個斷點或者是一個信號),gdb會自動選擇信號或斷點發生的線程作為當前線程;也就是說,當一個信號或者一個斷點在一個線程THREAD_A中發生而導致gdb中斷了你的程序,那麼,gdb會自動選擇該線程(THREAD_A)作為當前線程,執行info threads後,顯示的線程狀態信息列表中,當前線程的前面帶有一個星號'*';

Copyright © Linux教程網 All Rights Reserved