前言
當(dāng)前,我們可以使用 make/makefile 來程序化執(zhí)行代碼文件;可以使用 gcc/g++ 等編譯器來編譯代碼;可以使用 vim 編輯器來編寫代碼;其實在 Linux 當(dāng)中還有一個工具,可以實現(xiàn)調(diào)試工作,這個工具就是 -- gdb。
在了解調(diào)試器之前,你應(yīng)該對代碼的發(fā)布版本做一些了解:
我們在 VS 當(dāng)中,在開始執(zhí)行代碼之前,可以選擇以兩種方式執(zhí)行這個代碼:debug & release :
一般在開發(fā)期間使用的都是 debug 模式,在編寫好代碼之后,如果我們的代碼提交到遠(yuǎn)端,到客戶手上的時候,比如在公司當(dāng)中,用git提交到公司的 倉庫當(dāng)中,公司就可以以release 版本發(fā)布,同時,測試人員測試的模式也是 release 版本的。
debug 版本能調(diào)試 而 release 版本不能調(diào)試。而且,debug 版本代碼文件要比 release 版本文件要大上不少。release 版本在執(zhí)行效率上也要比 debug 要高。
那么出現(xiàn)上述幾種區(qū)別的原因就是:debug 版本的代碼,在形成可執(zhí)行文件的時候,會生成調(diào)試信息,而 這個調(diào)試信息 是 release 版本沒有的。
在 Linux 當(dāng)中使用 gcc/g++ 編譯器編譯可執(zhí)行文件時候,默認(rèn)是以 release?的方式進行發(fā)布的。無法直接調(diào)試,如果要想以 dubug 方式發(fā)布,在使用 gc/g++ 編譯的時候,需要帶上 -g 選項來進行編譯。?
?在 下述博客的? 進行了詳細(xì)介紹,包括 如果查看 debug 文件等等:
Linux - 配置系統(tǒng)白名單 - gcc/g++_linux 白名單-CSDN博客
gdb 調(diào)試器
?使用如下命令,就可以調(diào)試一個 可執(zhí)行文件:
gdb 可執(zhí)行文件名
如果,在使用上述命令之后,出現(xiàn)如下這個談話框,并且沒有任何報錯的話,說明,當(dāng)前你已經(jīng)進入了 調(diào)試的 交互界面了:
如上所示,text 是一個可以調(diào)試的可執(zhí)行程序,出現(xiàn)上述界面代表你已經(jīng)成功進入到 調(diào)試界面了。?
如果想退出的話,可以使用 q/quit 。
?此時,我們還看不到代碼,因為gdb 是以命令行的形式來進行 查看代碼 和 調(diào)試代碼的,不像 windows 當(dāng)中 是使用圖形化界面來實現(xiàn),我們可以直接看到代碼。
此時,你可以使用 list/l 來查看全部代碼?:
你可以發(fā)現(xiàn),我們上述是使用了兩次命令(一次 list 一次 l),才查看到了全部的代碼,其實 單獨使用 list/l 不一定會從第一行顯示全部的代碼。?所以,我們的帶上參數(shù):
l/list 0? (0代表行數(shù),可是代碼當(dāng)中任意行開始)就代表 從第 0 行開始顯示:
?
?上述都是只打印了 10 行,如果我們想顯示全部代碼的話,下面有一種方式:
當(dāng)我們使用了 l/list 0 這個命令之后,其實 gdb 是會自動記錄上一條指令的,當(dāng)我們按下 回車之后(前提是 使用了 l/list 0 這個命令之后 ) ,他就會認(rèn)為我們此時想要繼續(xù)執(zhí)行 list/l 命令,那么他就會繼續(xù)顯示代碼(在上一次顯示的最后一行的下一行開始):
而且,最后還會提示,從共有多少行代碼。?
還可以 使用下述命令,來查看 代碼當(dāng)中某一個函數(shù)的全部代碼:
list/l 函數(shù)名?
那么我們在調(diào)試的時候,肯定不只是 查看代碼,而是要先找到問題所在,對于問題的所在,我們可以看報錯位置,然后推測報錯位置,然后使用條件斷點,或者是在代碼當(dāng)中寫入停止的代碼語句,比如用 if 判斷一下 ,當(dāng) 程序走到哪一步的時候就停止,這種方法在 程序棧幀迭代較深的 代碼當(dāng)中尤其適用,比如 在 八數(shù)碼問題當(dāng)中,我們很有可能會遍歷到很深的 狀態(tài)矩陣當(dāng)中(在八數(shù)碼問題當(dāng)中我們 不管使用 A* 還是sm 啟發(fā)式算法,都會遍歷出很多的 狀態(tài)矩陣,這些狀態(tài)矩陣就是 我們在挪動 其中方塊,移動不同方塊,和方塊移動位置不同,都會產(chǎn)生不同的狀態(tài)矩陣(也就是一種中間過程的情況)),關(guān)于八數(shù)碼問題的介紹具體請看下述博客:八數(shù)碼問題-c語言_八數(shù)碼問題c語言代碼_chihiro1122的博客-CSDN博客
之所以在上述舉出這么多篇幅的例子,就是想說:調(diào)試最離不開的就是斷點,不管是是在最開始的時候,比如在 VS 當(dāng)中我們需要打上斷點,然后按下 F5 程序就會直接運行到 斷點處停止,然后我們進行 進步一調(diào)試;還有一種可能是在 調(diào)試階段打上斷點,在調(diào)試過程當(dāng)中可能也會遇到程序運行比較麻煩的地方,也可以在調(diào)試過程當(dāng)中打上斷點來跳過這一步驟。
那么 gdb 作為一個好用的 調(diào)試器,他肯定也是支持?jǐn)帱c的,那么接下來,將會對 gdb 當(dāng)中打斷點方式進行說明:
在 gdb 當(dāng)中 運行程序,打斷點?
在 gdb 調(diào)試界面下,使用 r 命令就可以直接運行程序:
?
由于此時我們沒有在程序當(dāng)中打上斷點,所以此時程序就直接運行到結(jié)束了。退出的時候也是正常退出的,就類似在 VS 當(dāng)中的 F5/ shift F5 開始調(diào)試一樣。
使用 在 gdb 調(diào)試窗口下,使用 b 行號?可以在當(dāng)前調(diào)試文件當(dāng)中的 指定行打上斷點。此時我們在使用 r 命令既可以從程序運行,運行到 指定斷點處 停下來了:
?
?在 VS 當(dāng)中如果我們在某一行打上了斷點,是可以直接看到 這個紅色的斷點在哪一行存在的:
?但是在 gdb 當(dāng)中,這個斷點我們是看不見的,就算我們 打完斷點之后再去 使用 l 0?查看整個代碼還是看不了斷點:
其實使用 info b 就可以查看我們打上的所有所在斷點行數(shù)了:
我們發(fā)現(xiàn),在使用 info b 命令之后,出現(xiàn)的不只有 斷點所在代碼行數(shù),還有一些其他信息,這些信息所代表的意思,如下所示:
?我們發(fā)現(xiàn),在gdb 當(dāng)中的斷點是有 編號的,當(dāng)我們像刪除某一個斷點的時候,不能像之前一樣使用 行號來刪除斷點,而是應(yīng)該使用 斷點的編號來刪除斷點。在 gdb 當(dāng)中我們可以使用 d 斷點編號
來刪除某一個結(jié)點:
?而且,需要注意的是,我們設(shè)置的斷點這些信息,都是在當(dāng)前gdb 運行進程之內(nèi)使用的,也就是說,我們在當(dāng)前 gdb 調(diào)試窗口下設(shè)置的各個調(diào)試信息,如果退出一個 gdb 然后在進去 gdb 調(diào)試的話,盡管是同一個文件,在上一次 gdb 進程當(dāng)中保存的 調(diào)試信息都會刪除。
?在gbd 當(dāng)中進行 逐語句 逐過程 調(diào)試
在 VS 當(dāng)中有兩種 逐語句的方式 調(diào)試,一種是 F10 逐過程,另一種是 F11??逐語句。
逐語句好理解,逐過程其實就是跳過一個過程,一個函數(shù)可以被稱為一個過程。
使用 n/next 命令就可以進行 逐過程調(diào)試:
?當(dāng)我們進行調(diào)試運行代碼之后,在斷點信息當(dāng)中還有多出一個信息:斷點被命中的次數(shù):
像上述兩個斷點,被命中的次數(shù)都是 1。?
使用 s 命令 進行 逐語句調(diào)試:
gdb 當(dāng)中的監(jiān)視窗口
?在 VS 當(dāng)中的監(jiān)視窗口也是必不可少的,監(jiān)視可以極大的方便我們查看某變量當(dāng)前是否合法,或則可以查看很多很多的信息,具體要看自己怎么使用調(diào)試:
?在gdb 當(dāng)中也肯定不能缺少 調(diào)試窗口,但是因為 gdb 不是圖形化界面,所以要 手動輸入某個變量,來讓 gdb 知道你當(dāng)前想要查看哪一個變量的值。
我們使用 p 變量名/變量的某些變形之后的值 這個命令就可以查看 這個變量的值,或者是這個變量變形之后的值了。
此時我們就知道了,a 變量的值 在當(dāng)前程序執(zhí)行狀態(tài)下 就是 10。?
和VS 當(dāng)中的調(diào)試窗口一樣,我們還可以通過調(diào)試窗口,查看到 a 的地址等等變形信息:
?但是,你有沒有發(fā)現(xiàn)上述的監(jiān)視太挫了,VS 當(dāng)中還可以一遍進行 逐步調(diào)試,一般查看 變量的值,而上述 的 p 還有一個一個打出來。
其實 gdb 當(dāng)中也是有 常顯示 監(jiān)視窗口命令的:display?變量名/變量的某些變形之后的值? ?,這樣的話,輸入的變量 就會一直跟著你調(diào)試一起 走:
?如果不想 常顯示變量值,可以使用 undisplay 命令,但是這個命令不能再后面直接加 變量名等等信息來刪除掉 該變量信息的 監(jiān)視信息:
?
可以發(fā)現(xiàn),是不行的。
?需要注意的是:在常顯示的 變量信息 當(dāng)中,每一個信息是有自己的編號的,和上述 刪除斷點一樣,需要按照編號來進行刪除,也就是 使用 undisplay 常顯示變量信息編號 刪除某一個常顯示信息:
可以發(fā)現(xiàn)此時就刪除成功了。
對于 常顯示信息編號,就是顯示信息的最左側(cè)數(shù)字:
?
?until 跳轉(zhuǎn)指令 - finish 結(jié)束當(dāng)前函數(shù)執(zhí)行指令
?假設(shè)我們現(xiàn)在在一個函數(shù)的循環(huán)體當(dāng)中,現(xiàn)在已經(jīng)陷入了這個循環(huán)體,但是這個我們又想跳出當(dāng)前這個循環(huán)體 ,查看這個循環(huán)體結(jié)束之后,修改的內(nèi)容,此時我們就可以使用 until 指定行 來跳轉(zhuǎn)到某一行。
?像上述我們使用 until 跳轉(zhuǎn)出函數(shù)的循環(huán)體的時候,需要查看我們想要跳轉(zhuǎn)到那一行,如果當(dāng)前只是想要 跳出這個函數(shù)的話,也就是只是把當(dāng)前函數(shù)執(zhí)行完畢,然后查看這個函數(shù)的執(zhí)行結(jié)果,那么我們可以在函數(shù)當(dāng)中運行時,使用 finish 指令來結(jié)束當(dāng)前函數(shù)的執(zhí)行。
?finish 的使用場景,舉個例子,比如當(dāng)前寫的代碼崩掉了,但是在主函數(shù)當(dāng)中有 很多個函數(shù)需要我們?nèi)ヅ袛?,此時我們要想知道是哪一個函數(shù)當(dāng)中導(dǎo)致代碼奔潰的話,就可以執(zhí)行具體函數(shù)當(dāng)中,使用 finish 來執(zhí)行函數(shù)體,看看是那個函數(shù)導(dǎo)致程序奔潰的。
continue 跳到下一個斷點
?VS 當(dāng)中你肯定使用 F5 來跳到下一個斷點處,在gdb 當(dāng)中使用 countinue 也能達(dá)到 直接從當(dāng)前位置跳到下一個斷點的功能。
?修改斷點的 Enb 值
VS 當(dāng)中右鍵 斷點可以選擇禁用斷點,或者是啟用斷點,同樣的 在gdb 當(dāng)中有 Enb 值,這個值只有兩個值,y or n ,也就代表著這個斷點是否被啟用。
使用 disable 斷點編號 就可以修改 Enb 值:
?此時我們 r 運行程序,直接就運行到 第三個斷點處了,第一第二個斷點已經(jīng)被跳過了(上述是21 行是因為 20 行斷點處為空行,gdb 自動跳過 了)
?gdb 命令總結(jié)
gdb 當(dāng)中還有很多命令,像 b 命令打斷點,可以用 b 文件名:行號??給指定可執(zhí)行文件的行號位置處打上斷點。
而 b 函數(shù)名 這種方式打出的斷點,本質(zhì)是就是在函數(shù)體的起始位置處,也就是函數(shù)體的第一行代碼當(dāng)中打上斷點:
文章來源:http://www.zghlxwxcb.cn/news/detail-724915.html
?總結(jié):文章來源地址http://www.zghlxwxcb.cn/news/detail-724915.html
- list/l 行號:顯示binFile源代碼,接著上次的位置往下列,每次列10行。
- list/l 函數(shù)名:列出某個函數(shù)的源代碼。
- r或run:運行程序。
- n 或 next:單條執(zhí)行。
- s或step:進入函數(shù)調(diào)用
- break(b) 行號:在某一行設(shè)置斷點
- break 函數(shù)名:在某個函數(shù)開頭設(shè)置斷點
- info break :查看斷點信息。
- finish:執(zhí)行到當(dāng)前函數(shù)返回,然后挺下來等待命令
- print(p):打印表達(dá)式的值,通過表達(dá)式可以修改變量的值或者調(diào)用函數(shù)
- p 變量:打印變量值。
- set var:修改變量的值
- continue(或c):從當(dāng)前位置開始連續(xù)而非單步執(zhí)行程序
- run(或r):從開始連續(xù)而非單步執(zhí)行程序
- delete breakpoints:刪除所有斷點
- delete breakpoints n:刪除序號為n的斷點
- disable breakpoints:禁用斷點
- enable breakpoints:啟用斷點
- info(或i) breakpoints:參看當(dāng)前設(shè)置了哪些斷點
- display 變量名:跟蹤查看一個變量,每次停下來都顯示它的值
- undisplay:取消對先前設(shè)置的那些變量的跟蹤
- until X行號:跳至X行
- breaktrace(或bt):查看各級函數(shù)調(diào)用及參數(shù)
- info(i) locals:查看當(dāng)前棧幀局部變量的值(相當(dāng)于查看 VS 當(dāng)中本地變量這個對話框)
- quit:退出gdb
?
到了這里,關(guān)于Linux - 還不懂 gdb 調(diào)試器?(調(diào)試軟件)的文章就介紹完了。如果您還想了解更多內(nèi)容,請在右上角搜索TOY模板網(wǎng)以前的文章或繼續(xù)瀏覽下面的相關(guān)文章,希望大家以后多多支持TOY模板網(wǎng)!