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