gdb 入门
gdb 入門
簡介
gdb是GNU開源組織發(fā)布的一個強大的Linux下的程序調試工具。
一般來說,GDB主要幫助你完成下面四個方面的功能:
1、啟動你的程序,可以按照你的自定義的要求隨心所欲的運行程序。
2、可讓被調試的程序在你所指定的調置的斷點處停住。(斷點可以是條件表達式)
3、當程序被停住時,可以檢查此時你的程序中所發(fā)生的事。
4、你可以改變你的程序,將一個BUG產生的影響修正從而測試其他BUG。
gdb可以調試的對象
gdb 可以調試的語言
Ada, Assembly, C, C++, D, Fortran, Go, Objective-C, OpenCL, Modula-2, Pascal, Rust
gdb 可以調試的文件類型
注意在編譯時需要加上-g選項。gdb可以調試的文件類型有三種:
二進制文件。
gdb a.out
core文件。通常,我們在遇到錯誤時得到一個core文件(如果沒有,請通過ulimit -a命令查看core file siez是否為0,若為0,通過ulimit -c unlimited改為unlimited即可)
gdb a.out core.12345
運行中的進程,其中[1234]時要調試的進程號
gdb -p 1234
gdb的常用命令(入門)
本小節(jié)僅介紹入門級的常用命令,稍微進階的用法會慢慢補全。
以下索引表解釋常用命令基本的含義,有些細節(jié)會在下一小節(jié)具體說。
| help (h) | 查看命令幫助 |
| run (r) | 重新開始運行文件 |
| run argv[1] argv[2] | 調試時命令行傳參 |
| start | 單步執(zhí)行,運行程序,停在第一執(zhí)行語句 |
| list (l) | 查看源代碼 |
| set | 設置變量的值 |
| next (n) | 單步調試(逐過程,函數直接執(zhí)行) |
| step (s) | 單步調試(逐語句,跳入自定義函數內部執(zhí)行) |
| braktrace (bt) | 查看函數的調用的棧幀和層級關系 |
| frame (f) | 切換函數的棧楨 |
| info (i) | 查看函數內部局部變量的值 |
| finish | 結束當前函數,返回到調用點 |
| continue (c) | 繼續(xù)運行(至下一個斷點或程序結束) |
| print (p) | 打印值 |
| quit (q) | 退出gdb |
| break (b) | 設置斷點 |
| info breakpoints(i break) | 查看當前設置的所有斷點 |
| enable/disable breakpoints | 啟用 / 禁用斷點 |
| delete num(d num) | 刪除第num個斷點 |
| display | 追蹤查看具體的變量值 |
| undisplay | 取消追蹤觀察變量 |
| watch | 被設置觀察點的變量發(fā)生修改時,打印顯示 |
| info watchpoints(i watch) | 顯示觀察點 |
| x | 查看內存x/20xw 顯示20個單元,16進制,4字節(jié)每單元 |
幾個常用的命令詳解
list
list 可簡寫為l,可以列出所調試程序的代碼
break
gdb調試時使用break命令來設置斷點,簡寫為b,有如下幾種下斷點地方法:
break function:在進入指定的函數function處打斷點,C++中可以使用class::function或function(type, type)格式來指定函數名稱
break filename:function:在指定文件的指定函數處打斷點
break linenumber:在指定的行數打斷點
break filename:linenumber:在指定文件的指定行數打斷點
break +/- offeset:在當前行的前面或后面打斷點
break *address:在程序運行的指定地址出打斷點
break:在下一條命令處停止運行
break .. if condition:在在處理某些循環(huán)體中可使用此方法進行調試,其中…可以是上述的break lineNumber、break +/-offset中的參數,其中condition表示條件,在條件成立時程
序即停止運行,如設置break if i=100表示當i為100時程序停止運行。
查看斷點時,也可以使用info命令如info breakpoints [n]、info break [n]其中n 表示斷點號來查看斷點信息。
可以通過delete命令刪除所有的斷點
next
使用next命令單步執(zhí)行程序代碼,next的單步不會進入函數的內部,與next對應的step命令則在單步執(zhí)行一個函數時進入函數內部,類似于VC++中的step into,其用法為next count,單步跟蹤,如果有函數調用不會進入函數,如果后面不加count表示一條一條的執(zhí)行,加count表示執(zhí)行后面的count條指令。
continue
continue:當程序遇到斷點停下來之后,可以執(zhí)行continue繼續(xù)執(zhí)行到下一個斷點或到程序結束。
簡寫為p,可以通過print命令查看參數或程序運行數據
值得注意的是print輸出可以指定顯示變量的輸出格式:
| x | 十六進制 |
| d | 十進制 |
| u | 十六進制無符號數 |
| o | 八進制 |
| t | 二進制 |
| c | 字符格式 |
| f | 浮點數格式 |
print可以輸出東西可多:全局變量,靜態(tài)全局變量,局部變量,如果你的局部變量和全局變量發(fā)生沖突(也就是重名),一般情況下是局部變量會隱藏全局變量。
全局變量利用::,例如在1.c中看x:(gdb)p "1.c"::x
數組(動):p *array@len
array:數組的首地址,len:數據的長度
數組(靜):直接p數組名
所有寄存器的值:info registers
查看指定的寄存器的值:p $eip
結構體。如果你想很漂亮的輸出結構體請設置set print pretty on,打開print pretty這個東西,沒錯,輸出很漂亮滴。
disassemble
用disassemble function來查看匯編代碼,如下圖示某個main函數的反匯編代碼:
我們可以通過反匯編代碼的偏移量來在匯編代碼中打上斷點,比如我們想要在圖中紅色箭頭處打斷點,只需b *main+45。
我們可以通過disassemble /m function指令,來將C/C++源代碼和其反匯編一起顯示,這樣會更加直觀:
backtrace
可以簡寫為bt,功能為顯示函數的棧。
當你的程序調用了一個函數,函數的地址,函數參數,函數內的局部變量都會被壓入“棧”(Stack)中。你可以用這條命令來查看當前的棧中的所有信息。
在遞歸時可以很方便地查看棧上各個遞歸函數的棧幀:
圖中的Delete函數會被遞歸調用,功能時刪除二叉搜索樹種的某個節(jié)點,具體功能不重要,這里是為了展示遞歸函數多層遞歸時通過backtrace來查看棧幀信息。
顯示棧頂的幾個層的信息:bt n
顯示棧底下的幾層信息:bt -n
但是,如果要查看某一層的信息,你需要在切換當前的棧,一般來說,程序停止時,最頂層的棧就是當前棧,如果你要查看棧下面層的詳細信息,首先要做的是切換當前棧。這就要用到下面的frame命令。
frame
可以簡寫為f,n是一個從0開始的整數,是棧中的層編號。比如:frame 0,表示棧頂,即當前函數的棧幀,frame 1,表示棧的第二層,即調用當前函數的函數的棧幀。
up n:表示向棧的上面移動n層,可以不打n,表示向上移動一層。
down n:表示向棧的下面移動n層,可以不打n,表示向下移動一層。
info f:會打印出更為詳細的當前棧層的信息。
layout
用于分割窗口,可以一邊查看代碼,一邊測試。如下圖是layout src的窗口展示:
| layout src | 顯示源代碼窗口 |
| layout asm | 顯示匯編窗口 |
| layout regs | 顯示源代碼/匯編和寄存器窗口 |
| layout split | 顯示源代碼和匯編窗口 |
| layout next | 顯示下一個layout |
| layout prev | 顯示上一個layout |
另外我們可以通過一些功能鍵調整窗口選項:
Ctrl + L,刷新窗口
Ctrl + x,再按1:單窗口模式,顯示一個窗口
Ctrl + x,再按2:雙窗口模式,顯示兩個窗口
Ctrl + x,再按a:回到傳統(tǒng)模式,即退出layout,回到執(zhí)行l(wèi)ayout之前的調試窗口。
Ref
https://www.gnu.org/software/gdb/
https://blog.csdn.net/awm_kar98/article/details/82840811
http://blog.chinaunix.net/uid-29611934-id-5168746.html
總結
- 上一篇: 为什么说旅游城市房价不会跌
- 下一篇: 启辰d60工作台怎么拆解?