Linux進階編程--04.GDB偵錯工具(設定斷點)

來源:互聯網
上載者:User

標籤:

調試已啟動並執行程式
  1. 在UNIX下用ps查看正在啟動並執行程式的PID(進程ID),然後用gdb PID格式掛接正在啟動並執行程式。
  2. 先用gdb 關聯上原始碼,並進行gdb,在gdb中用attach命令來掛接進程的PID。並用detach來取消掛接的進程。
暫停 / 恢複程式運行

偵錯工具中,暫停程式運行是必須的,GDB可以方便地暫停程式的運行。你可以設定程式的在哪行停住,在什麼條件下停住,在收到什麼訊號時停往等等。以便於你查看運行時的變數,以及運行時的流程。

當進程被gdb停住時,你可以使用info program 來查看程式的是否在運行,進程號,被暫停原因。

在gdb中,我們可以有以下幾種暫停方式:斷點(BreakPoint)、觀察點(WatchPoint)、捕捉點(CatchPoint)、訊號(Signals)、線程停止(Thread Stops)。如果要恢複程式運行,可以使用c或是continue命令。

設定斷點(BreakPoint)

我們用break命令來設定斷點。正面有幾點設定斷點的方法:

  • break :在進入指定函數時停住。C++中可以使用class::function或function(type,type)格式來指定函數名。
  • break :在指定行號停住。
  • break +offset / break -offset :在當前行號的前面或後面的offset行停住。offiset為自然數。
  • break filename:linenum :在源檔案filename的linenum行處停住。
  • break filename:function :在源檔案filename的function函數的入口處停住。
  • break *address :在程式啟動並執行記憶體位址處停住。
  • break :break命令沒有參數時,表示在下一條指令處停住。
  • break … if : …可以是上述的參數,condition表示條件,在條件成立時停住。比如在迴圈境體中,可以設定break if i=100,表示當i為100時停住程式。

查看斷點時,可使用info命令,如下所示:(註:n表示斷點號)

  • info breakpoints [n]
  • info break [n]
設定觀察點(WatchPoint)

觀察點一般來觀察某個運算式(變數也是一種運算式)的值是否有變化了,如果有變化,馬上停住程式。我們有下面的幾種方法來設定觀察點:

  • watch :為運算式(變數)expr設定一個觀察點。一量運算式值有變化時,馬上停住程式。
  • rwatch :當運算式(變數)expr被讀時,停住程式。
  • awatch :當運算式(變數)的值被讀或被寫時,停住程式。
  • info watchpoints :列出當前所設定了的所有觀察點。
設定捕捉點(CatchPoint)

你可設定捕捉點來補捉程式運行時的一些事件。如:載入共用庫(動態連結程式庫)或是C++的異常。設定捕捉點的格式為:

  • catch : 當event發生時,停住程式。event可以是下面的內容:

    1. throw 一個C++拋出的異常。(throw為關鍵字)
    2. catch 一個C++捕捉到的異常。(catch為關鍵字)
    3. exec 調用系統調用exec時。(exec為關鍵字,目前此功能只在HP-UX下有用)
    4. fork 調用系統調用fork時。(fork為關鍵字,目前此功能只在HP-UX下有用)
    5. vfork 調用系統調用vfork時。(vfork為關鍵字,目前此功能只在HP-UX下有用)
    6. load 或 load 載入共用庫(動態連結程式庫)時。(load為關鍵字,目前此功能只在HP-UX下有用)
    7. unload 或 unload 卸載共用庫(動態連結程式庫)時。(unload為關鍵字,目前此功能只在HP-UX下有用)
  • tcatch :只設定一次捕捉點,當程式停住以後,應點被自動刪除。

維護停止點

上面說了如何設定程式的停止點,GDB中的停止點也就是上述的三類。在GDB中,如果你覺得已定義好的停止點沒有用了,你可以使用delete、clear、disable、enable這幾個命令來進行維護。

  • clear : 清除所有的已定義的停止點。
  • clear / clear : 清除所有設定在函數上的停止點。
  • clear / clear : 清除所有設定在指定行上的停止點。
  • 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。
  • condition :清除斷點號為bnum的停止條件。

還有一個比較特殊的維護命令ignore,你可以指定程式運行時,忽略停止條件幾次。

  • ignore :表示忽略斷點號為bnum的停止條件count次。
為停止點設定運行命令

我們可以使用GDB提供的command命令來設定停止點的運行命令。也就是說,當啟動並執行程式在被停止住時,我們可以讓其自動運行一些別的命令,這很有利行自動化調試。對基於GDB的自動化調試是一個強大的支援。

commands [bnum]... command-list ...end

為斷點號bnum指寫一個命令列表。當程式被該斷點停住時,gdb會依次運行命令列表中的命令。

例如:

break foo if x>0commandsprintf "x is %d/n",xcontinueend

斷點設定在函數foo中,斷點條件是x>0,如果程式被斷住後,也就是,一旦x的值在foo函數中大於0,GDB會自動列印出x的值,並繼續運行程式。
如果你要清除斷點上的命令序列,那麼只要簡單的執行一下commands命令,並直接在打個end就行了。

斷點菜單

在C++中,可能會重複出現同一個名字的函數若干次(函數重載),在這種情況下,break 不能告訴GDB要停在哪個函數的入口。當然,你可以使用break 也就是把函數的參數類型告訴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 6Breakpoint 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 :單步跟蹤,如果有函數調用,他會進入該函數。進入函數的前提是,此函數被編譯有debug資訊。很像VC等工具中的step in。後面可以加count也可以不加,不加表示一條條地執行,加表示執行後面的count條指令,然後再停住。
  • next :同樣單步跟蹤,如果有函數調用,他不會進入該函數。很像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 : 在GDB中定義一個訊號處理。訊號可以以SIG開頭或不以SIG開頭,可以用定義一個要處理訊號的範圍(如:SIGIO-SIGKILL,表示處理從SIGIO訊號到SIGKILL的訊號,其中包括SIGIO,SIGIOT,SIGKILL三個訊號),也可以使用關鍵字all來標明要處理所有的訊號。一旦被調試的程式接收到訊號,運行程式馬上會被GDB停住,以供調試。其可以是以下幾種關鍵字的一個或多個。

    • nostop :當被調試的程式收到訊號時,GDB不會停住程式的運行,但會打出訊息告訴你收到這種訊號。
    • stop :當被調試的程式收到訊號時,GDB會停住你的程式。
    • print :當被調試的程式收到訊號時,GDB會顯示出一條資訊。
    • noprint :當被調試的程式收到訊號時,GDB不會告訴你收到訊號的資訊。
    • pass / noignore :當被調試的程式收到訊號時,GDB不處理訊號。這表示,GDB會把這個訊號交給被偵錯工具會處理。
    • nopass / ignore :當被調試的程式收到訊號時,GDB不會讓被偵錯工具來處理這個訊號。
  • info signals / info handle :查看有哪些訊號在被GDB檢測中。

線程(Thread Stops)

如果你程式是多線程的話,你可以定義你的斷點是否在所有的線程上,或是在某個特定的線程。GDB很容易幫你完成這一工作。

break thread / break thread if … :linespec指定了斷點設定在的來源程式的行號。threadno指定了線程的ID,注意,這個ID是GDB分配的,你可以通過“info threads”命令來查看正在運行程式中的線程資訊。如果你不指定thread 則表示你的斷點設在所有線程上面。
你還可以為某線程指定斷點條件。如:

(gdb) break frik.c:13 thread 28 if bartab > lim

當你的程式被GDB停住時,所有的運行線程都會被停住。這方便你你查看運行程式的總體情況。而在你恢複程式運行時,所有的線程也會被恢複運行。那怕是主進程在被單步調試時。



來自為知筆記(Wiz)

Linux進階編程--04.GDB偵錯工具(設定斷點)

聯繫我們

該頁面正文內容均來源於網絡整理,並不代表阿里雲官方的觀點,該頁面所提到的產品和服務也與阿里云無關,如果該頁面內容對您造成了困擾,歡迎寫郵件給我們,收到郵件我們將在5個工作日內處理。

如果您發現本社區中有涉嫌抄襲的內容,歡迎發送郵件至: info-contact@alibabacloud.com 進行舉報並提供相關證據,工作人員會在 5 個工作天內聯絡您,一經查實,本站將立刻刪除涉嫌侵權內容。

A Free Trial That Lets You Build Big!

Start building with 50+ products and up to 12 months usage for Elastic Compute Service

  • Sales Support

    1 on 1 presale consultation

  • After-Sales Support

    24/7 Technical Support 6 Free Tickets per Quarter Faster Response

  • Alibaba Cloud offers highly flexible support services tailored to meet your exact needs.