用GDB调试程序(三)
上面說了如何設置程序的停止點,GDB中的停止點也就是上述的三類。在GDB中,如果你覺得已定義好的停止點沒有用了,你可以使用delete、clear、disable、enable這幾個命令來進行維護。
??? clear
??????? 清除所有的已定義的停止點。
??? clear <function>
??? clear <filename:function>
??????? 清除所有設置在函數上的停止點。
??? clear <linenum>
??? clear <filename:linenum>
??????? 清除所有設置在指定行上的停止點。
??? delete [breakpoints] [range...]
??????? 刪除指定的斷點,breakpoints為斷點號。如果不指定斷點號,則表示刪除所有的斷點。range 表示斷點號的范圍(如:3-7)。其簡寫命令為d。
比刪除更好的一種方法是disable停止點,disable了的停止點,GDB不會刪除,當你還需要時,enable即可,就好像回收站一樣。
??? disable [breakpoints] [range...]
??????? disable所指定的停止點,breakpoints為停止點號。如果什么都不指定,表示disable所有的停止點。簡寫命令是dis.
??? enable [breakpoints] [range...]
??????? enable所指定的停止點,breakpoints為停止點號。
??? enable [breakpoints] once range...
??????? enable所指定的停止點一次,當程序停止后,該停止點馬上被GDB自動disable。
??? enable [breakpoints] delete range...
??????? enable所指定的停止點一次,當程序停止后,該停止點馬上被GDB自動刪除。
?
五、停止條件維護
前面在說到設置斷點時,我們提到過可以設置一個條件,當條件成立時,程序自動停止,這是一個非常強大的功能,這里,我想專門說說這個條件的相關維護命令。一般來說,為斷點設置一個條件,我們使用if關鍵詞,后面跟其斷點條件。并且,條件設置好后,我們可以用condition命令來修改斷點的條件。(只有break和watch命令支持if,catch目前暫不支持if)
??? condition <bnum> <expression>
??????? 修改斷點號為bnum的停止條件為expression。
??? condition <bnum>
??????? 清除斷點號為bnum的停止條件。
還有一個比較特殊的維護命令ignore,你可以指定程序運行時,忽略停止條件幾次。
??? ignore <bnum> <count>
??????? 表示忽略斷點號為bnum的停止條件count次。
?
六、為停止點設定運行命令
我們可以使用GDB提供的command命令來設置停止點的運行命令。也就是說,當運行的程序在被停止住時,我們可以讓其自動運行一些別的命令,這很有利行自動化調試。對基于GDB的自動化調試是一個強大的支持。
??? commands [bnum]
??? ... command-list ...
??? end
??? 為斷點號bnum指寫一個命令列表。當程序被該斷點停住時,gdb會依次運行命令列表中的命令。
??? 例如:
??????? break foo if x>0
??????? commands
??????? printf "x is %d/n",x
??????? continue
??????? end
??????? 斷點設置在函數foo中,斷點條件是x>0,如果程序被斷住后,也就是,一旦x的值在foo函數中大于0,GDB會自動打印出x的值,并繼續運行程序。
如果你要清除斷點上的命令序列,那么只要簡單的執行一下commands命令,并直接在打個end就行了。
七、斷點菜單
在C++中,可能會重復出現同一個名字的函數若干次(函數重載),在這種情況下,break <function>不能告訴GDB要停在哪個函數的入口。當然,你可以使用break <function(type)>也就是把函數的參數類型告訴GDB,以指定一個函數。否則的話,GDB會給你列出一個斷點菜單供你選擇你所需要的斷點。你只要輸入你菜單列表中的編號就可以了。如:
??? (gdb) b String::after
??? [0] cancel
??? [1] all
??? [2] file:String.cc; line number:867
??? [3] file:String.cc; line number:860
??? [4] file:String.cc; line number:875
??? [5] file:String.cc; line number:853
??? [6] file:String.cc; line number:846
??? [7] file:String.cc; line number:735
??? > 2 4 6
??? Breakpoint 1 at 0xb26c: file String.cc, line 867.
??? Breakpoint 2 at 0xb344: file String.cc, line 875.
??? Breakpoint 3 at 0xafcc: file String.cc, line 846.
??? Multiple breakpoints were set.
??? Use the "delete" command to delete unwanted
???? breakpoints.
??? (gdb)
可見,GDB列出了所有after的重載函數,你可以選一下列表編號就行了。0表示放棄設置斷點,1表示所有函數都設置斷點。
八、恢復程序運行和單步調試
當程序被停住了,你可以用continue命令恢復程序的運行直到程序結束,或下一個斷點到來。也可以使用step或next命令單步跟蹤程序。
??? continue [ignore-count]
??? c [ignore-count]
??? fg [ignore-count]
??????? 恢復程序運行,直到程序結束,或是下一個斷點到來。ignore-count表示忽略其后的斷點次數。continue,c,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” ,當運行完這個命令后,單步跟蹤會在打出程序代碼的同時打出機器指令(也就是匯編代碼)
九、信號(Signals)
信號是一種軟中斷,是一種處理異步事件的方法。一般來說,操作系統都支持許多信號。尤其是UNIX,比較重要應用程序一般都會處理信號。UNIX定義了許多信號,比如SIGINT表示中斷字符信號,也就是Ctrl+C的信號,SIGBUS表示硬件故障的信號;SIGCHLD表示子進程狀態改變信號;SIGKILL表示終止程序運行的信號,等等。信號量編程是UNIX下非常重要的一種技術。
GDB有能力在你調試程序的時候處理任何一種信號,你可以告訴GDB需要處理哪一種信號。你可以要求GDB收到你所指定的信號時,馬上停住正在運行的程序,以供你進行調試。你可以用GDB的handle命令來完成這一功能。
??? handle <signal> <keywords...>
??????? 在GDB中定義一個信號處理。信號<signal>可以以SIG開頭或不以SIG開頭,可以用定義一個要處理信號的范圍(如:SIGIO-SIGKILL,表示處理從SIGIO信號到SIGKILL的信號,其中包括SIGIO,SIGIOT,SIGKILL三個信號),也可以使用關鍵字all來標明要處理所有的信號。一旦被調試的程序接收到信號,運行程序馬上會被GDB停住,以供調試。其<keywords>可以是以下幾種關鍵字的一個或多個。
??????? nostop
??????????? 當被調試的程序收到信號時,GDB不會停住程序的運行,但會打出消息告訴你收到這種信號。
??????? stop
??????????? 當被調試的程序收到信號時,GDB會停住你的程序。
??????? print
??????????? 當被調試的程序收到信號時,GDB會顯示出一條信息。
??????? noprint
??????????? 當被調試的程序收到信號時,GDB不會告訴你收到信號的信息。
??????? pass
??????? noignore
??????????? 當被調試的程序收到信號時,GDB不處理信號。這表示,GDB會把這個信號交給被調試程序會處理。
??????? nopass
??????? ignore
??????????? 當被調試的程序收到信號時,GDB不會讓被調試程序來處理這個信號。
??? info signals
??? info handle
??????? 查看有哪些信號在被GDB檢測中。
十、線程(Thread Stops)
如果你程序是多線程的話,你可以定義你的斷點是否在所有的線程上,或是在某個特定的線程。GDB很容易幫你完成這一工作。
??? break <linespec> thread <threadno>
??? break <linespec> thread <threadno> if ...
??????? linespec指定了斷點設置在的源程序的行號。threadno指定了線程的ID,注意,這個ID是GDB分配的,你可以通過“info threads”命令來查看正在運行程序中的線程信息。如果你不指定thread <threadno>則表示你的斷點設在所有線程上面。你還可以為某線程指定斷點條件。如:
???
??????? (gdb) break frik.c:13 thread 28 if bartab > lim
??? 當你的程序被GDB停住時,所有的運行線程都會被停住。這方便你你查看運行程序的總體情況。而在你恢復程序運行時,所有的線程也會被恢復運行。那怕是主進程在被單步調試時。
出處:http://blog.csdn.net/haoel/article/details/2881
總結
以上是生活随笔為你收集整理的用GDB调试程序(三)的全部內容,希望文章能夠幫你解決所遇到的問題。
- 上一篇: 跟我一起写 Makefile(十二)
- 下一篇: 用GDB调试程序(四)