天天看點

用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停住時,所有的運作線程都會被停住。這友善你你檢視運作程式的總體情況。而在你恢複程式運作時,所有的線程也會被恢複運作。那怕是主程序在被單步調試時.

本文來自CSDN部落格,轉載請标明出處:

http://blog.csdn.net/haoel/archive/2003/07/21/2881.aspx