天天看點

gdb調試

調試工具:

gdb

unix程式員最常用的調試工具是gdb,大多數linux系統應該預先安裝了gdb。如果沒有預先安裝該工具,則必須下載下傳gcc編譯器程式包。

ddd

随着gui(圖形使用者界面)越來越流行,大量的unix環境下運作的基于gui的調試器被開發出來。其中的大多數工具都是gdb的gui前端:使用者通過gui發出指令,gui将這些指令傳遞給gdb。ddd就是其中的一種工具。

如果你的系統還沒有安裝ddd,則可以下載下傳該工具。例如,centos系統上,指令

将自動處理整個安裝過程。

主要調試器操作

1 單步調試源代碼

可以安排程式的執行run在某個地方暫停,以便檢查變量的值,進而得到關于程式錯誤所在位置的線索。下面是可用來暫停程式執行的一些方法。

斷點

  正如前面所說,調試工具會在指定斷電處暫停程式的執行。在gdb中是通過break指令及其行号完成的,在ddd中是在相關代碼行的任意空白處右擊并選擇set breakpoint來完成的。

單步調試

  gdb的next指令讓gdb執行下一行,然後暫停。step指令的作用于此類似,隻是在函數調用時step指令會進入函數,而next導緻程式執行的暫停出現在下次調用函數時。ddd有對應的next和step菜單項。

恢複操作

  在gdb中,continue指令通知調試其恢複執行并繼續,直到遇到斷點為止。ddd中有一個對應的菜單項。

臨時斷點

  在gdb中,tbreak指令和break相似,但是這一指令設定的斷電的有效期隻到首次到達指定行時為止。在ddd中臨時斷點的設定方式為:在源文本視窗中要設定斷點的代碼行的任意空白處右擊,然後選擇set temporary breakpoint。

gdb中還有建立特殊類型的一次性斷點的指令:until和finish。ddd的指令工具中有對應的until和finish項。

程式執行的典型調試模式如下(以gdb為例):單擊一個斷點後,通過gdb的next指令一次移動一行代碼,或通過step指令單步調試一段時間,以便仔細檢查靠近斷點處的程式狀态和行為。做完這些操作後,可以用continue指令讓調試器繼續執行程式,直到遇到下一個斷點為止,其間不需要暫停。

gdb的暫停機制

有3種方式可以通知gdb的暫停程式的執行。

斷點:通知gdb在程式中的特定位置暫停執行。

監視點:通知gdb當特定記憶體位置(或者涉及一個或多個位置的表達式)的值發生變化時暫停執行

捕獲點:通知gdb當特定事件發生時暫停執行。

斷點概述

斷點就像程式中的絆網:在程式中的特定“位置”設定斷點,當到達那一點時,調試器會暫停程式的執行(在gdb這樣的基于文本的調試器的情況下,會出現指令行提示符)。

gdb中關于“位置”的含義是非常靈活的,它可以指各種源代碼行、代碼位址、源代碼檔案中的行号或者函數的入口等。

gdb執行到斷點行之前,gdb顯示的是将要執行的代碼行。

然而,gdb的工作針對的是機器語言指令,而不是源代碼行,一行代碼可能對應于數行機器語言。

可以使用info breakpoints指令獲得斷點資訊。使用delete + 斷點編号來删除斷點。

設定斷點

在gdb中設定斷點

gdb中有許多指定斷點的方式,下面是一些最常見的方法。

break function

  在函數function()的入口(第一行可執行代碼)處設定斷點。

  (gdb) break main

  在main()的入口處設定斷點。

break line_number

  在目前活動源代碼檔案的line_number處設定斷點。對于多行程式,這要麼是上次使用list指令檢視其内容的檔案,要麼是包含main()的檔案。

  (gdb) break 35

  它在檔案的第35行處設定了一個斷點。

break filename:line_number

  在源代碼檔案filename的line_number處設定斷點。如果filename不在目前工作目錄中,則可以給出相對路徑名或者完全路徑名來幫助gdb查找該檔案,例如:

  (gdb) break source/bed.c:35

break filename:function

  在檔案filename中的函數function()的入口處設定斷點。重載函數或者使用同名靜态函數的程式可能需要使用這種方式,例如:

  (gdb) break bed.c:parsearguments

  正如我們看到的,當設定一個斷點時,該斷點的有效性會持續到删除、禁用或退出gdb時。然而,臨時斷點是首次到達後就會自動删除的斷點。臨時斷點使用tbreak指令設定,它與break采用相同類型的參數。例如,tbreak foo.c在檔案的第10行設定臨時斷點。

  當同一行源代碼上有多個斷點時會發生什麼情況。當gdb使用多個斷點中斷一行源代碼時,它隻會中斷一次。換言之,當它到達該行代碼時,如果恢複執行,會忽略恰好在同一行的其他斷點。事實上,gdb知道是哪個斷點“觸發”了程式停止執行。在具有多個斷點的代碼行上,觸發中斷的斷點将是辨別符編号最小的斷點。

 斷點的持久性

如果在重新修改編譯源代碼期間不退出gdb。例如,當發現并修複了一個程式錯誤,但是其他程式錯誤仍然存在時,不應當退出gdb然後重新進入來使用程式的新版本。這樣做有些不必要地繁瑣,而且還會不得不重新進入斷點。

如果在修改和重新編譯代碼時沒有退出gdb,那麼在下次執行gdb的run指令時,gdb會感覺到代碼已經修改,并自動重新加載新版本。

删除和禁用斷點

如果确認不再需要目前斷點,那麼可以删除該斷點。gdb中有兩個用來删除斷點的指令。delete指令用來基于辨別符删除斷點,clear指令使用建立斷點相同的文法删除斷點。

delete breakpoint_list

删除斷點使用數值辨別符。斷點可以是一個數字,比如delete 2删除第二個斷點;也可以是數字清單,比如delete 2 4 删除第二個和第四個斷點。

delete

删除所有斷點。除非執行也可以放在.gdbinit啟動檔案中的set confirm off指令,否則gdb會要求确認删除操作。

clear

清除gdb将執行的下一個指令處的斷點。這種方法适用于要删除gdb已經到達的斷點的情況。

clear function、clear filename:function、clear line_number和clear filename:line_number

這些指令根據位置清楚斷點,工作方式與對應的break指令相似。

在gdb中禁用斷點

每個斷點都可以被啟用或禁用。隻有當gdb遇到啟用的斷點時,才會暫停程式的執行;它會忽略禁用的斷點。預設情況下,斷點的生命期從啟用時開始。

使用disable breakppoint-list指令禁用斷點,使用enable breakpoint-list指令啟用斷點,其中breakpoint-list是使用空格分隔的清單,其中有一個或多個斷點辨別符。例如

(gdb) disble 3

将禁用第三個斷點。類似地,

(gdb) enable 1 5

将啟用第一個和第五個斷點。

不帶任何參數地執行disable指令将禁用所有現有斷點。類似地,不帶參數地執行enable指令會啟用所有現有斷點。

還有一個enable once指令。在斷點下次引起gdb暫停執行後被禁用。文法為:

enable once breakpoint-list

繼續閱讀