這里只是一個(gè)摘要。具體的細節還需要去看manual。
1 info 用來(lái)描述你的程序的狀態(tài),比如info b就是顯示出當前的程序的所有斷點(diǎn).
2 set 用來(lái)設置一些環(huán)境變量的值,比如set prompt $.
3 show用來(lái)描述gdb自己的狀態(tài).
編譯要用-g選項.
然后用gdb +程序名,或者直接gdb后,用file + 文件名加載程序.
1 run/r 運行程序.
2 set args 設置程序的參數.
3 path directory 加一個(gè)目錄到環(huán)境變量path
4 set directory 設置gdb的工作目錄
5 pwd 當前的工作目錄
6 attch process-id 調試 運行的進(jìn)程
dettach 當調試進(jìn)程完畢,release 掉gdb的控制.
調試多線(xiàn)程.
1 thread threadno 選擇當前的線(xiàn)程.
2 info thread 查看當前程序的線(xiàn)程.
debug多進(jìn)程:
默認情況下,當fork一個(gè)子進(jìn)程之后,gdb會(huì )繼續debug父進(jìn)程,而子進(jìn)程會(huì )運行下去.不過(guò)我們能夠改變這個(gè).
set follow-fork-mode mode 這里mode可以為parent或者child. parent是默認值,而child的話(huà)就是gdb繼續debug子進(jìn)程,而父進(jìn)程會(huì )運行下去.
如果你想要同時(shí)debug父子進(jìn)程,也可以設置:
set detach-on-fork mode 默認是on,也就是只能debug一個(gè)進(jìn)程,如果改為off則可以同時(shí)debug父子進(jìn)程.
保存一個(gè)書(shū)簽稍后返回.
checkpoint 保存當前的程序的狀態(tài).
restart checkpoint-id 返回到checkpoint-id那個(gè)點(diǎn).這個(gè)值可以用info checkpoint來(lái)查看
breakpoint,watchpoint以及catchpoint
breakpoint 就是斷點(diǎn).
watchpoint 就是用來(lái)檢測變量的改變,他可以看做是特殊的斷點(diǎn),也就是當變量改變時(shí)停止程序.
catchpoint 是另外一種特殊的斷點(diǎn),用來(lái)監測某一事件的發(fā)生,有點(diǎn)類(lèi)似其它語(yǔ)言中的異常.
1 設置Breakpoint
break location 設置斷點(diǎn).location可以為行號,函數名或者指令地址.
break 設置斷點(diǎn),不過(guò)這個(gè)斷點(diǎn)為當前棧幀的下一條指令.
break location if condition 當condition為真時(shí),程序到達這個(gè)斷點(diǎn)才起作用.
tbreaks args, 一次性的斷點(diǎn).
rbreaks regex 設置斷點(diǎn)在所有與regex匹配的函數.這個(gè)正則表達式的語(yǔ)義與grep的相同.
2 設置watchpoint
watch expr[thread threadno] 設置檢測變量expr,后面可以跟著(zhù)改變這個(gè)變量的線(xiàn)程.如果跟著(zhù)線(xiàn)程號,則說(shuō)明只有當這個(gè)線(xiàn)程改變變量時(shí),程序才會(huì )stop.
rwatch expr[thread threadno] 上面是監測變量改變,而這個(gè)命令是監測程序讀取變量.
awatch expr[thread threadno] 當expr要么被讀,要么被寫(xiě)時(shí),程序直接break.
3 設置catchpoint
catch event 當event發(fā)生的時(shí)候程序停止.
event可以是下面的幾種類(lèi)型: throw ,catch,exception,exception unhandled,assert,exec,fork,vfork.
tcatch event 一次性的監測事件.
刪除斷點(diǎn)
clear 刪除在當前的棧幀的將要被執行的下一條指令斷點(diǎn).
clear location 刪除location位置的斷點(diǎn).其實(shí)更有用的是下面幾個(gè)命令:
clear function,clear filename:function ,clear linenum,clear filename:linenum.
delete [breakpoints][range...] 其實(shí)也就是刪除多個(gè)斷點(diǎn),如果沒(méi)有range,咋就是刪除全部斷點(diǎn).
關(guān)閉斷點(diǎn)
一個(gè)斷點(diǎn)(包括 watchpoint和catchpoint)可以有下面四種狀態(tài).
打開(kāi),關(guān)閉,enabled once,enabled for deletion
disable [breakpoints][range..] 關(guān)閉指定的斷點(diǎn)或者全部斷點(diǎn)(如果沒(méi)有range)
enable [breakpoints][range..] 打開(kāi)指定的斷點(diǎn)或者全部斷點(diǎn)(如果沒(méi)有range)
enable [breakpoints] once range 臨時(shí)打開(kāi)指定的斷點(diǎn)(也就是說(shuō)是一次性的,.
enable [breakpoints] delete range 臨時(shí)打開(kāi)指定的斷點(diǎn)并只工作一次,也就是一次之后這個(gè)斷點(diǎn)將會(huì )被刪除.
break condition
contidition bnum expression 當expression為真的時(shí)候,程序到達這個(gè)斷點(diǎn)才會(huì )停止.
contidition bnum 從斷點(diǎn)bnum刪除掉一個(gè)condition.
ignore bnum count 設置一個(gè)斷點(diǎn)bnum的忽略次數為count.也就是只有count次數后,這個(gè)斷點(diǎn)才會(huì )起作用.
斷點(diǎn)命令列表
這個(gè)主要是用來(lái)當到達這個(gè)斷點(diǎn),程序停止后,你想要執行一連串的命令.格式為:
- command [bnum]
- ... command-list ..
- end
command [bnum]... command-list ..end
指定一堆命令給斷點(diǎn)bnum.如果想刪除命令的話(huà)就把command-list置為空就行了.
如果沒(méi)有bnum,則這個(gè)command指的是最后設置的一個(gè)斷點(diǎn).
這里有個(gè)例子:
- break 403
- commands
-
- silent
-
- set x = y + 4
-
- cont
- end
break 403commands///不輸出任何東西silent///改變x的值set x = y + 4///然后continuecontend
接下來(lái)來(lái)看continue和step
continue表示讓程序繼續執行,直到下一個(gè)斷點(diǎn)或者執行完畢。
step表示讓程序執行一行代碼或者說(shuō)一條機器指令(依賴(lài)于你選擇的命令)。
下面來(lái)看命令:
- continue [ignore-count]
- c [ignore-count]
- fg [ignore-count]
continue [ignore-count]c [ignore-count]fg [ignore-count]
這幾個(gè)命令都是resume一個(gè)程序,然后參數ignore-count表示忽略當前這個(gè)斷點(diǎn)的次數。
step [count]
繼續運行程序直到抵達一個(gè)新的代碼行(它會(huì )跟入函數).這里要記住step只會(huì )停止在source line的第一條指令。
如果加上count參數則表示它會(huì )step count次。如果遇到斷點(diǎn)則會(huì )停止。
next [count]
和step很類(lèi)似,區別就是不會(huì )跟進(jìn)函數。
- set step-mode
- set step-mode on
- set step-mode off
set step-modeset step-mode onset step-mode off
on就可以使step停止在沒(méi)有debug信息的函數的第一條指令上。off則是直接執行完這個(gè)函數。
這里要注意上面的命令都只是跳一行代碼。而不是一條指令。
util 繼續運行直到source line通過(guò)了當前的行。這個(gè)命令主要是針對循環(huán)語(yǔ)句中的step。比如你在循環(huán)結尾設置util,則只有當循環(huán)退出時(shí)才會(huì )在這個(gè)斷點(diǎn)停止。而不是每次都停止。
util location 繼續運行直到指定的location,或者當前的棧幀返回。
advance location 繼續運行直到給定的location,這個(gè)相比與上面的命令,它就象全局的。
stepi [arg]
執行一條機器指令。 arg表示次數。
nexti [arg]
和next類(lèi)似只不過(guò)執行的是一條機器指令。
下來(lái)來(lái)看信號。
gdb可以監測在你的程序中的任何信號。
來(lái)看命令。
handle signal [keywords...]
這個(gè)命令用來(lái)改變信號signal(名字或者數字)在gdb中的行為。
其中關(guān)鍵就是keywords.在這里keywords可以為下面幾種類(lèi)型:
1 nostop gdb接收到信號不會(huì )停止程序,而只是打印出一段message
2 stop 和上面類(lèi)似只不過(guò)會(huì )停止程序。
3 print 當信號發(fā)生必須打印一條消息通知。
4 noprint 信號發(fā)生,gdb將不會(huì )打印任何東西。
5 pass和noignore 這兩個(gè)是同義的。表示信號對你的程序是可見(jiàn)的。
6 nopass和ignore 這兩個(gè)也是同義的。和上面相反。。
在gdb中,當你的程序由于一個(gè)信號而停止后,直到你繼續執行,否則信號對你的程序是不可見(jiàn)得。也就是說(shuō)當gdb捕捉到信號,我們可以用nopass或者ignore來(lái)使信號對我們的程序為不可見(jiàn)。
最后來(lái)看下多線(xiàn)程程序的調試。
首先來(lái)看多線(xiàn)程調試的幾種模式。
1 all-stop模式。
在這種模式中,當你的程序在gdb由于任何原因而停止,此時(shí)所有的線(xiàn)程都會(huì )停止。而不僅僅是當前的線(xiàn)程。一般來(lái)說(shuō)gdb不能單步所有的線(xiàn)程。因為線(xiàn)程調度gdb是無(wú)法控制的。無(wú)論什么時(shí)候當gdb停止你的程序,它都會(huì )自動(dòng)切換到觸發(fā)斷點(diǎn)的那個(gè)線(xiàn)程。
在一些os中我們可以通過(guò)lock線(xiàn)程調度器,從而達到只有一個(gè)線(xiàn)程在運行。
set scheduler-locking mode
設置模式,如果mode是off,則表示沒(méi)有lock,則任何線(xiàn)程在任何時(shí)候都有可能在運行。當mode為on的時(shí)候,鎖定其他的線(xiàn)程,也就是只有當前線(xiàn)程在執行。也就是你單步的時(shí)候其他線(xiàn)程是不會(huì )運行的。這個(gè)對我們只關(guān)注本線(xiàn)程比較重要。
默認情況下,當你鍵入step或者next命令時(shí),gdb只允許當前進(jìn)程的線(xiàn)程運行。我們可以通過(guò)命令來(lái)修改這個(gè)默認值。
set schedule-multiple mode
當mode為on則所有進(jìn)程的所有線(xiàn)程都勻許運行。否則只有當前的進(jìn)程的線(xiàn)程能夠resume。
2 none-stop模式。
顧名思義,當程序在gdb中停止,只有當前的線(xiàn)程會(huì )被停止,而其他的線(xiàn)程將會(huì )繼續運行。
這個(gè)時(shí)候step,next這些命令就只對當前的線(xiàn)程起作用。
我們要打開(kāi)這個(gè)模式需要這樣操作:
- # Enable the async interface.
- set target-async 1
- # If using the CLI, pagination breaks non-stop.
- set pagination off
- # Finally, turn it on!
- set non-stop on
# Enable the async interface.set target-async 1# If using the CLI, pagination breaks non-stop.set pagination off# Finally, turn it on!set non-stop on
這里要注意打開(kāi)這個(gè)模式必須得在你attach或運行這個(gè)程序或者進(jìn)程之前才能進(jìn)行。
Background Execution
gdb執行命令有兩種類(lèi)型:前臺的(同步)和后臺(異步)的。
區別很簡(jiǎn)單,前臺的話(huà),gdb在輸出提示符之前會(huì )等待程序report一些線(xiàn)程已經(jīng)終止的信息。而異步的則是直接返回。
我們需要顯式打開(kāi)異步模式。
set target-async on
下面就是支持異步的命令:
- run
- attach
- step
- stepi
- next
- nexti
- continue
- finish
- until
runattachstepstepinextnexticontinuefinishuntil
通過(guò)上面我們可以看到異步模式主要用在none-stop模式中。
如果你想停止后臺運行的程序,那么使用interrupt
在all-stop模式中interrupt將會(huì )停止所有的線(xiàn)程。而在none-stop中只會(huì )停止當前線(xiàn)程。interrupt -a此時(shí)就能停止所有線(xiàn)程。’
當你有多個(gè)線(xiàn)程,你此時(shí)只想給某個(gè)線(xiàn)程設置斷點(diǎn),這個(gè)時(shí)候可以用這個(gè)命令:
break linespec thread threadno
break linespec thread threadno if ...
linespec為源碼行號,threadno為線(xiàn)程id。
最后來(lái)看下多線(xiàn)程調試中可能會(huì )遇到的一個(gè)問(wèn)題:
如果一個(gè)線(xiàn)程在一個(gè)斷點(diǎn),或者由于其他什么原因停止,此時(shí)另外的線(xiàn)程阻塞在一個(gè)系統調用。這個(gè)時(shí)候這個(gè)系統調用就有可能會(huì )過(guò)早的返回。因此我們在調用系統調用,最好都要檢測它的返回值。
舉個(gè)例子:
sleep (10);
這個(gè)我們應該改成這樣:
- int unslept = 10;
- while (unslept > 0)
- unslept = sleep (unslept);
int unslept = 10;while (unslept > 0)unslept = sleep (unslept);