無數(shù)次被問道:你在終端下怎么調(diào)試更高效?或者怎么在 Vim 里調(diào)試,?好吧,,今天統(tǒng)一回答下,,我從來不在 vim 里調(diào)試,因為它還不成熟,。那除了命令行 GDB 裸奔以外,,終端下還有沒有更高效的方法?能夠讓我事半功倍,?
當然有,,選擇恰當?shù)墓ぞ吆头椒ǎ?GDB 調(diào)試效率成倍的提升并沒有任何問題,。當然,,前提條件是你至少會在使用最原始的 GDB。
裸奔狀態(tài):原始的 GDB 命令行
穿上各種衣服前,,至少得先學會裸奔,,找份簡單的 GDB cheat sheet 對照一下:
生產(chǎn)環(huán)境中出現(xiàn)崩潰時,因線上服務器一般沒有開發(fā)環(huán)境,,也無配套源代碼,,所以程序崩潰后,如果你懶得把 core 文件拖回到開發(fā)機檢查,,可以先在線上服務器先簡單gdb看一下,。
GDB命令密密麻麻,常用的也就表格上那幾條,,比如進去以后第一步先用 bt 查看一下調(diào)用棧,,info local查看一下本地變量,再配合 up/down 在整個調(diào)用棧的不同層次之間上下移動一下,,檢查各處局部變量的值,,print 一下某個表達式,即便沒代碼,,看下符號和反匯編,,一般也能調(diào)試個七七八八。
碰到復雜點的 BUG,,必須配合源代碼了,,那你得把 core 文件拉到開發(fā)環(huán)境中,再用 gdb 對照源代碼調(diào)試,,配合 list [行號] 指令查看當前運行的源代碼,,再配合其他方法進行調(diào)試。
那么這時候,,如果調(diào)試復雜度繼續(xù)上升,,你需要不斷的斷點,每次 next / step 單步完后你都需要 list 一下前后源代碼,或者用 disassemble [函數(shù)名/地址] 查看一下指令的話,,不少人會感覺到抓狂,,這時我們需要給裸奔的 GDB 穿條內(nèi)褲了。
穿上內(nèi)褲的 GDB - TUI
這是 gdb 自帶的文本界面,,使用 gdb -tui 命令啟動,,比如:
gdb -tui hello
即可打開我們的文本界面:
上方是源代碼窗口,下面是 gdb 終端,,窗口管理快捷鍵模仿 emacs,,使用 c-x o 進行窗口切換,如果你還想查看指令窗口,,可以輸入:layout split
然后你單步的時候上面的源代碼窗口會跟著滾動,,比之前不停的 list 方便不少吧,要看前后源代碼可以繼續(xù) c-x o 切換窗口后上下滾動,。
有時候你 up/down 切換了棧幀后,,上面的代碼也許來不及更新,那么你用 update 指令,,讓上面的代碼窗口定位到你最新的執(zhí)行位置,有時也需要 CTRL-L 重繪下整個界面,。
在 gdb 自帶的 tui 模式中,,你不但可以隨時查看代碼/指令,還可以查看寄存器,。好吧,,其實 gdb再簡陋,本身還是配套了一條內(nèi)褲的,,只是很多人忘記拿出來穿了,。
穿上內(nèi)衣:gdbinit
如果上述文本 TUI的信息不夠豐富的話,也許你會對 .gdbinit 感興趣,,~/.gdbinit 是一個 gdb配置腳本,,可以設定一些由 python 編寫的插件,比如 peda:
在 ~/.gdbinit 上面配置了 peda 后,,可以看到命令提示符就從 (gdb) 變成了 gdb-peda$ ,。每敲一個單步命令,peda 都會顯示出無比豐富的信息,,你還可以配置添加更多,,配合高亮,你可以得到一個加強版的命令行,。
不過這個我用的并不多,,因為它會影響 TUI 模式的界面,我不喜歡在我的 gdb 里搞太多亂七八糟的東西。同時,,當我們的調(diào)試需求繼續(xù)變得更加復雜,,你要不停的斷點,頻繁的單步,,這些傳統(tǒng)命令行里不停的輸入各種指令顯然已經(jīng)讓我們疲憊不堪了,,能否直接在界面上查看源代碼并且直接在代碼上快捷鍵斷點,快捷鍵單步呢,?
可以啊,,試試 cgdb。
穿上外套的 GDB:cgdb
CGDB 類似 gdb tui 分為終端窗口和代碼窗口:
上面的代碼窗口稱為 cgdb mode, 下面的 gdb 窗口稱為 gdb mode,,調(diào)試就是不停的在兩種模式間切換,,按鍵模仿 vim,按 ESC 切換回 cgdb 模式,,按 i 切換到 gdb 模式,。
這看起來和 TUI gdb 差不多啊,?除了語法高亮外它比 gdb tui 高效在哪里呢,?答案是:大部分操作皆可在 cgdb mode 下(即源代碼窗口)用快捷鍵操作。
方向鍵 或者 hjkl 移動光標,,page-down/up 或 c-f / c-b 前后翻頁,,按 o鍵會列出當前可執(zhí)行文件的源代碼列表,可以切換查看其他相關代碼文件,,按 / 或者 ,?可以進行文檔搜索。
上面這些快捷鍵基本和 vim 對應,,能讓你方便的瀏覽源代碼,,同時在代碼窗口可以用空格鍵來切換斷點,還有其他一些快捷鍵:
F5 - Send a run command to GDB.
F6 - Send a continue command to GDB.
F7 - Send a finish command to GDB.
F8 - Send a next command to GDB.
F10 - Send a step command to GDB.
更多快捷鍵見【這里】,,這下單步和斷點比原來輕松多啦,,你基本可以呆在源代碼窗口里不出來,大部分時候不用再到 gdb 命令行里一條條 next/step 的輸入了,。
編輯一下 ~/.cgdb/cgdbrc ,,簡單調(diào)教下使用更方便:
這里大概設置了搜索大小寫不敏感,tab 大小,,分屏方式(默認改為左右分屏),,搜索高亮,以及加了一個 F9 的快捷鍵,,用于跳出循環(huán)(默認沒有這個快捷鍵):
現(xiàn)在大家都是寬屏顯示器了,,默認改成左右分屏(要 cgdb 7.0才支持)舒服不少。
cgdb 還有更多功能,比如沒有源文件時可以查看匯編,,或者交叉查看源代碼和匯編,,設置 mark 等等,具體見它的官方文檔吧,。
這個小工具能將你從大量 gdb 命令行中解脫出來,,配置文件還可以讓你按喜好綁定各種命令到快捷鍵上。
穿戴整齊:Emacs GDB
CGDB 雖然大部分操作可以用快捷鍵進行,,但是仍然有不少時候需要切換回右邊的 gdb mode 中去敲命令,,比如當你需要每單步一次就用 info local 查看一下局部變量或者 print 一下某個全局變量的值的時候,頻繁的左右切換會讓你疲于奔命,。
所有在調(diào)試一些相對復雜的問題時,,上面這些工具 hold 不住了,作用平時 Vim 寫代碼的人,,我也從不拒絕用 emacs 的 gdb mode 來調(diào)試一些復雜問題,,毫無疑問 emacs 是目前終端下最強的 GDB 前端。
從來沒用過 emacs 都沒關系,,只要安裝一個 emacs 記得下面幾條命令就可以調(diào)試了:
切換文件:c-x c-f (先按 ctrl_x 再按 ctrl_f),,輸入文件名時可以用 tab 補全
移動光標:方向鍵,或者 c-f, c-b, c-p, c-n,;翻頁 pgup/down 或者 c-v / m-v
切換緩存:c-x b 切換當前窗口里的緩存,,c-x c-b 打開新窗口切換緩存。
窗口操作:c-x o 窗口切換,,c-x 2 / c-x 3 上下/左右分屏,c-x 0 / c-x 1 關閉 / 獨占
輸入命令:m-x (按 ALT_x)輸入命令可以用 tab 補全,,c-g 退出命令輸入,。
當然,別忘記退出命令是 c-x c-c,,這就夠了,,首先我們啟動 emacs:
按下 m-x (alt+x),提示輸入命令(如果終端軟件 alt 鍵不靈,,那可以設置一下終端軟件,,或者一秒內(nèi)先按 ESC,再按 x鍵,,在 xterm 終端下是等價的),,鍵入 “gdb”敲回車:
下面會問你怎么運行gdb,輸入gdb的 shell 啟動命令行回車后開始 gdb 模式:
看到這里也許你會問,,這和直接命令行 gdb 有區(qū)別么,?別急,繼續(xù) m-x 輸入命令:
馬上滿足你:
左上是 GDB 終端,從上到下分別是:GDB終端,,本地變量監(jiān)控,,源代碼,程序輸出,,棧幀,,斷點列表。
當然你可以接著在 gdb 終端里輸入你想要的指令,,但大部分時候我們會在源代碼窗口工作,,使用 c-x o 將窗口定位到源代碼窗口,使用下面命令或者對應快捷鍵進行操作:
這些 gud- 開頭的命令都是 emacs gdb-mode 下通用調(diào)試器的操作命令,,他們和 gdb 命令一一對應,,可以用 m-x 輸入這些命令,還可以直接用快捷鍵操作,。
如果你想把某個窗口替換成反匯編或者寄存器的監(jiān)控,,那么可以用 m-x 輸入:
那么其中一個窗口就會被切換成反匯編窗口:
左上角的 gdb 終端被切換成反匯編窗口了,看完后記得 c-x b 切換回 gdb 控制臺,,如果你要避免某個窗口被切換走可以搜索 emacs 的 dedicated window,。再者,我們可以自己用窗口管理快捷鍵按照我們的喜好拆分布局:
比如重新拆分了一下,,把 gdb 終端挪到右邊,,輸出窗口下面,把原來顯示 gdb 終端的地方顯示為反匯編,?;旧夏阍?IDE 上見得到的調(diào)試手段,在 emacs 中都可以操作,,并且 emacs 還可以在 Windows 下用 gdb 調(diào)試 mingw 的程序,。
那么也許你會抱怨 emacs 下操作是在太麻煩了,沒關系,,稍微調(diào)教一下即可,。
調(diào)教 emacs gdb-mode
打開 ~/.emacs (windows下是 ~/_emacs)文件,輸入如下內(nèi)容:
解釋一下,,最上面設定了 ALT + 方向鍵就可以在窗口中跳轉(zhuǎn),,如果你終端 alt+方向不靈的話可以改成 C-left, C-right 等用 ctrl + 方向鍵移動窗口,后面設定了一些常用命令的快捷,。
最后設置了默認打開 gdb-many-windows,,最好增加下面一段,允許鼠標操作:
這下 xterm 下你可以自用的用鼠標點擊切換窗口,,點擊按鈕,,用滾輪上下查看源代碼了:
這下自由多了,,ALT+方向或者鼠標點擊,直接窗口跳轉(zhuǎn),,并且用下面的命令操作:
F5 - 運行,,Shift + F5 - 繼續(xù)
F7/F8 代碼級單步, 以及 Shift-F7/F8 指令級單步
F9 - 設置斷點,,Shift-F9 刪除斷點
F10 - 跳出循環(huán),,Shift-F10 跳出函數(shù)
F4 - 移動到上一個調(diào)用棧幀,Shift-F4移動到下一個
右上角的本地變量窗口上面有兩個按鈕,,可以鼠標點擊切換顯示本地變量還是寄存器,。右下角的也有兩個按鈕切換顯示斷點還是線程。最上面綠色部分的按鈕也可以直接鼠標點擊,。
終于比我們最初的版本好用多了,,如果你喜歡折騰的話,你還可以定制 gdb-many-windows 的初始格局,,比如更復雜的:
徹底滿足你各種復雜的調(diào)試需求,,這里不展開了,有興趣見【這篇文章】,。
最后每次調(diào)試時打開 emacs, m-x輸入 gdb 再鍵入文件名很麻煩,?我們調(diào)教一下 .bashrc:
就能自動打開 emacs 并且切換到 gdb-mode 下面,展開我們的多窗口,,開始調(diào)試了,,是不是很愉快?
我平時調(diào)試沒環(huán)境會先使用 gdb-tui 先看看,,有環(huán)境或者問題復雜了我會打開 emacs 來調(diào)試,。后來
@zpan
給我介紹了 cgdb 以后,gdb-tui 就退役了,,無環(huán)境先用 cgdb 看個大概,,碰到復雜問題打開 emacs,經(jīng)過一番調(diào)教,,十分順手。
讓 GDB 變得更性感一些
其實到 emacs 已經(jīng)差不多了,,但如果你實在記不住這有限的幾個快捷鍵或者 gdb 命令,,那么還可以嘗試一下 gdbgui:
就會監(jiān)聽本地 5000 端口,這時我們可以用瀏覽器打開服務器上的地址完全用鼠標進行調(diào)試,。
中間是程序代碼,,下面是 GDB終端,上面可以切換源代碼,,可以控制運行/繼續(xù)/單步等,。右邊可以實時查看:本地變量,,調(diào)用棧幀,內(nèi)存地址,,斷點,,線程 等等。
還能可視化查詢數(shù)據(jù)結(jié)構(gòu):
鼠標點擊代碼左邊就可以設置/刪除斷點,,點擊上面的按鈕就能切換顯示匯編代碼,。基本上把 GDB的主要功能都用可視化的方式,,現(xiàn)代的網(wǎng)頁界面展示在你的面前,,不需要記住任何快捷鍵,鼠標點點點就可以了,。
同時,,這個 gdbgui 還支持 Windows 下的 gdb 調(diào)試。目前 gdbgui 還在活躍的開發(fā)中,,作為最漂亮的 gdb 前端,,相信它會越來越強大。
回顧一下
好了我們經(jīng)歷了從最開始 gdb 的命令行裸奔狀態(tài)到終端下最完善的調(diào)試環(huán)境 emacs gdb-mode,,再到性感的 gdbgui,。GDB 的好處就在于對內(nèi)可以引入各種插件,對外可以提供各種接口,,自己做好調(diào)試的事情,,前端界面可以完全交給其他程序來主導,不管是本地還是遠程,,所以才會有了各種各樣豐富的 GDB Front End,,還有各種遠程 GDB 工具。
它不會限制你說你只能這樣調(diào)試,,或者你只有唯一的一種 UI可以操作,,所以 GDB 的組合方式千千萬萬,用不著一談 GDB 就覺得只有原始的敲命令一種用法,,對吧,?上面么多用法,隨便選兩樣,,花不了半小時,,即可讓你終端下的調(diào)試工作加快不少。
更多信息可以來這里獲取==>>電子技術應用-AET<<