天天看點

GDB 常用指令詳解(下)

轉自:https://www.cnblogs.com/loveyan1314/articles/10314229.html

本文的核心内容:

  • disassemble 指令
  • set args 和 show args 指令
  • tbreak 指令
  • watch 指令
  • display 指令

disassemble 指令

當進行一些進階調試時,我們可能需要檢視某段代碼的彙編指令去排查問題,或者是在調試一些沒有調試資訊的釋出版程式時,也隻能通過反彙編代碼去定位問題,那麼 disassemble 指令就派上用場了。

GDB 預設反彙編為 AT&T 格式的指令,可以通過 show disassembly-flavor 檢視,如果習慣 intel 彙編格式可以用指令 set disassembly-flavor intel 來設定。

set args 和 show args 指令

很多程式需要我們傳遞指令行參數。在 GDB 調試中,很多人會覺得可以使用 gdb filename args 這種形式來給 GDB 調試的程式傳遞指令行參數,這樣是不行的。正确的做法是在用 GDB 附加程式後,在使用 run 指令之前,使用“set args 參數内容”來設定指令行參數。

還是以 redis-server 為例,Redis 啟動時可以指定一個指令行參數,它的預設配置檔案位于 redis-server 這個檔案的上一層目錄,是以我們可以在 GDB 中這樣傳遞這個參數:set args ../redis.conf(即檔案 redis.conf 位于目前程式 redis-server 的上一層目錄),可以通過 show args檢視指令行參數是否設定成功。【這個set args隻是針對程式啟動時設定的,main中的(argv)】

GDB 常用指令詳解(下)

如果單個指令行參數之間含有空格,可以使用引号将參數包裹起來:

GDB 常用指令詳解(下)

如果想清除掉已經設定好的指令行參數,使用 set args 不加任何參數即可。

GDB 常用指令詳解(下)

tbreak 指令

tbreak 指令也是添加一個斷點,第一個字母“t”的意思是 temporarily(臨時的),也就是說這個指令加的斷點是臨時的,所謂臨時斷點,就是一旦該斷點觸發一次後就會自動删除。添加斷點的方法與上面介紹的 break 指令一模一樣,這裡不再贅述。

GDB 常用指令詳解(下)

上述代碼,我們使用 tbreak 指令在 main() 函數處添加了一個斷點,當斷點觸發後,再次運作程式不再觸發斷點,因為這個臨時斷點已經被删除。

watch 指令

watch 指令是一個強大的指令,它可以用來監視一個變量或者一段記憶體,當這個變量或者該記憶體處的值發生變化時,GDB 就會中斷下來。被監視的某個變量或者某個記憶體位址會産生一個 watch point(觀察點)。【watch也是一種斷點類型( hw watchpoint)】

我在數年前去北京中關村軟體園應聘一個 C++ 開發的職位,當時一個面試官問了這樣一個問題:有一個變量其值被意外地改掉了,通過單步調試或者挨個檢查使用該變量的代碼工作量會非常大,如何快速地定位到該變量在哪裡被修改了?其實,面試官想要的答案是“硬體斷點”。具體什麼是硬體斷點,我将在後面進階調試課程中介紹,而 watch 指令就可以通過新增硬體斷點來達到監視資料變化的目的。watch 指令的使用方式是“watch 變量名或記憶體位址”,一般有以下幾種形式:

  • 形式一:整型變量
int i;
watch i
           
  • 形式二:指針類型
char *p;
watch p 與 watch *p
           
注意:watch p 與 watch *p 是有差別的,前者是檢視 *(&p),是 p 變量本身;後者是 p 所指記憶體的内容。我們需要檢視位址,因為目的是要看某記憶體位址上的資料是怎樣變化的。
  • 形式三:watch 一個數組或記憶體區間
char buf[128];
watch buf
           

這裡是對 buf 的 128 個資料進行了監視,此時不是采用硬體斷點,而是用軟中斷實作的。用軟中斷方式去檢查記憶體變量是比較耗費 CPU 資源的,精确地指明位址是硬體中斷。

式去檢查記憶體變量是比較耗費 CPU 資源的,精确地指明位址是硬體中斷。

注意:當設定的觀察點是一個局部變量時,局部變量無效後,觀察點也會失效。在觀察點失效時 GDB 可能會提示如下資訊:
Watchpoint 2 deleted because the program has left the block in which its expression is valid.
           

display 指令

display 指令監視的變量或者記憶體位址,每次程式中斷下來都會自動輸出這些變量或記憶體的值【如果沒有中斷下來,則不會顯示這些值】。例如,假設程式有一些全局變量,每次斷點停下來我都希望 GDB 可以自動輸出這些變量的最新值,那麼使用“display 變量名”設定即可。

With no argument, display all currently requested auto-display expressions.

Use "undisplay" to cancel display requests previously made.

可以使用 info display 檢視目前已經自動添加了哪些值,使用 delete display 清除全部需要自動輸出的變量,使用 delete diaplay 編号 删除某個自動輸出的變量:

GDB 常用指令詳解(下)

小結

到目前為止已把 GDB 常用的指令都介紹完了,不知道讀者是否能記得每一個指令的用途和用法?隻要了解了,記憶它們其實也不難,這些基礎指令,希望讀者能熟練掌握。