使用圖形化介面#
作者認為除錯是少數幾個圖形化介面明顯優於命令列的工作之一。原因是除錯需要同時呈現多種資料:原始碼、local 變數、call stack、log 訊息等。
如果你使用 Eclipse 或 Visual Studio,已經具備了良好的圖形化除錯環境。如果使用 gdb,有幾個 GUI 前端可選:
- DDD (DataDisplayDebugger) — 功能最完整的 Unix-based GUI 前端,不只支援 gdb,也支援 Perl (bashdb)、Bash (bashdb)、make (remake)、Python (pydb) 的 debugger,還提供資料結構視覺化
- gdb -tui 或
-— gdb 內建的文字介面模式 - cgdb — 提供 vi 風格鍵盤綁定的介面
儲存除錯指令#
將常用的除錯指令儲存到檔案中,下次除錯時自動載入,可以大幅提升效率。
gdb 的設定檔層次#
Visual Studio 和 Eclipse 會自動儲存 breakpoints 和 watchpoints 等 session 設定。gdb 則透過 .gdbinit 檔案:
$HOME/.gdbinit— 全域設定,所有 gdb session 都會載入myproject/.gdbinit— 專案特定設定,在該目錄啟動 gdb 時載入issue-1234— 特定問題的 breakpoints 和 watchpoints,用-x選項載入
實用的 gdb 設定#
set history save— 儲存指令歷史,下次可用方向鍵或搜尋回叫.inputrc設定 —set editing-mode vi或set editing-mode emacs切換鍵盤綁定
自訂 gdb 指令#
可以用 define 定義新指令,例如:
define sf
where
info args
info locals
end
document sf
Display current stack frame
endGitHub 上的 gdbinit Gist 收集了許多實用的 gdb 自訂指令,值得參考。
用 gdb 腳本進行自動化檢查#
gdb 腳本可以實現一些程式碼中不方便加入的自動化檢查。書中示範了一個驗證 lock 順序的腳本:
- 定義一個計數器變數
$nlock - 在
lock函式上設 breakpoint,命中時遞增計數器 - 在
unlock函式上設 breakpoint,命中時遞減計數器 - 用 conditional breakpoint 檢測 nested lock(
lock時$nlock > 0)和 duplicate unlock(unlock時$nlock <= 0) - 檢測到問題時印出 backtrace 並暫停程式
gdb 的 compile 指令#
新版 gdb 提供
compile指令,讓你直接在 gdb 中用應用程式的原生語言編譯和執行程式碼,可以存取 local 和 global 變數與函式。不過,複雜的除錯邏輯通常還是應該放在程式碼中。
在 gdb 內 build 程式#
在 gdb session 中執行 make 指令來重新編譯程式,可以保留你已輸入的所有設定。重新 run 時 gdb 會自動偵測執行檔已更新並重新載入。
重點回顧#
- 盡量使用圖形化介面進行除錯
- 設定 gdb 儲存指令歷史,並使用你慣用的鍵盤綁定
- 將常用指令放入 gdb 腳本(
.gdbinit),實現自動化檢查 - 在 gdb 內 build 程式,保留已建立的除錯設定