更多精彩內容,請關注微信公眾號:后端技術小屋
GDB全稱GDB Debugger。GDB具備各種調試功能,使用GDB的調試人員可以查看及修改程序的內部變量值。它是Linux C++開發者賴以生存的神器。本篇文章將簡要介紹GDB常用功能,希望對於初學者能起到快速入門的作用。
1. 綁定進程
gdb ./a.out # 綁定尚未運行的程序
gdb attach <pid> # 綁定正在運行的進程
2. 查看代碼
2.1 查看程序代碼
> dir <source_directory> # 添加cpp原文件目錄
> l # 默認顯示暫停處代碼
> l <function> # 顯示函數代碼
> l <file:function> # 顯示文件中某函數代碼
> l <file:line> # 顯示文件中指定行數代碼
2.2 查看匯編指令
> disass # 顯示當前匯編指令
> display/i $pc # 每次回到gdb命令行時,顯示當前匯編指令
3. 斷點
3.1 斷點設置
> b <file:line> # 設置文件中某行斷點
> b <file:function> # 設置文件中某函數斷點
> b <namespace::class::function> # 設置某類的成員函數斷點
> b <location> <thread-id> # 設置某個線程在某處的斷點
> b <location> if <condition> # 設置某處的條件斷點
3.2 斷點查看
> info b # 查詢所有斷點
3.3 斷點刪除/啟用/禁用
> d <break-id> # 刪除某斷點
> disable <break-id> # 禁用某斷點
> enable <break-id> # 啟用某斷點
3.4 斷點設置自動執行命令
> command <break-id>
> p <var> # 運行到斷點處時自動打印變量<var>
> end
4. 線程調試
pstack <pid> # 可事先dump某個進程下所有線程的thread id和backtrace,方便gdb調試
> info threads # 查看當前所有線程信息
> bt # 查看當前線程的backtrace
> bt full # 查看當前線程更詳細的backtrace(每個棧幀上的參數)
> thread <thread-id> # 切換到某一個線程
> set scheduler-locking on # 多線程環境下,只有當前被調試線程會執行
> set scheduler-locking off # 多線程環境下,除當前被調試線程之外的其他線程也在同步執行
> set scheduler-locking step # 多線程環境下,對當前被調試線程用step調試時,其他線程不會執行;使用next調試時,其他線程也許會執行
5. 運行控制
> r arg1 arg2 ... # 重新開始運行二進制
> stop # 暫停運行
> c # 繼續執行
> n # 單步執行,遇到函數則跳過
> s # 單步執行,遇到函數則跳入函數體
> finish # 運行直到跳出當前函數
> until line # 運行直到到達指定行
> call command # 運行C++命令
> shell # 進入shell模式,回到linux終端
> exit # 退出shell模式,回到gdb命令行
> set $var=XXX # 設置gdb變量
> set var=XXX # 設置程序中變量
6. 結束調試
detach # 如果通過gdb attach調試,detach之后,原進程將繼續執行
quit # 退出gdb
7. 調試core
一般情況下,當設置了ulimit -c unlimited
之后,當程序遇到異常時,會自動轉儲core文件,方便開發者查看分析現場。
但是,如果想對一個正常運行的進程進行轉儲, 可使用gcore
命令:
gcore <pid> # 將進程<pid>轉儲到core文件中
gdb -c core ./a.out # 調試core文件
> bt full # 查看異常的backtrace
8. 代碼窗口
gdb命令行中輸入CTRL + X或者CTRL + A,即可調出代碼窗口,再按一次退出代碼窗口。
注意: 在tui模式下,無法使用方向鍵獲取上一條或下一條命令,可使用ctrl+p和ctrl+n替代
9. 打印變量
9.1 打印普通變量
> p <var> # 打印變量<var>
9.2 打印protobuf message
> p <var>.DebugString() # 使用DebugString()將proto對象內部結構打印出來
9.3 打印內存地址
# n:為正整數,表示需要打印的內存單元個數
#
# f:打印格式, 如下
# - x: 十六進制
# - d: 十進制
# - u: 十六進制
# - o: 八進制
# - t: 二進制
# - a: 十六進制
# - c: 字符格式
# - f: 浮點數
#
# u: 內存單元大小,如下:
# - b: 單字節
# - h: 雙字節
# - w: 四字節
# - g: 八字節
#
# addr: 要打印的內存地址
> x/<n/f/u> <addr> # 打印內存地址
9.4 打印長字符串
gdb會限制打印字符串的最大長度。使用下列命令可修改限制:
> show print elements # 顯示字符串最大打印長度
> set print elements 0 # 取消字符串最大打印長度
9.5 打印CPU寄存器的值
> i r # 打印所有寄存器的值
> i r es # 打印寄存器es的值
10. 開啟日志
gdb默認不開啟日志。可使用如下命令開啟:
> set logging on # 設置gdb日志開啟,gdb會在當前目錄下生成gdb.txt記錄gdb命令行所有輸出結果,方便回溯歷史。
推薦閱讀
- STL源碼分析--vector
- zookeeper client原理總結
- redis實現分布式鎖
- 推薦幾個好用的效率神器
- C/C++關鍵字之restrict
- 現代C++之右值語義
- Python亂碼九問
- Linux Shell腳本攻略讀書筆記
更多精彩內容,請掃碼關注微信公眾號:后端技術小屋。如果覺得文章對你有幫助的話,請多多分享、轉發、在看。