国产 无码 综合区,色欲AV无码国产永久播放,无码天堂亚洲国产AV,国产日韩欧美女同一区二区

Linux | 調(diào)試器GDB的詳細(xì)教程【純命令行調(diào)試】

這篇具有很好參考價值的文章主要介紹了Linux | 調(diào)試器GDB的詳細(xì)教程【純命令行調(diào)試】。希望對大家有所幫助。如果存在錯誤或未考慮完全的地方,請大家不吝賜教,您也可以點擊"舉報違法"按鈕提交疑問。

linux gdb調(diào)試命令,# Linux基礎(chǔ)入門篇,linux,運(yùn)維,gdb,調(diào)試技巧
linux gdb調(diào)試命令,# Linux基礎(chǔ)入門篇,linux,運(yùn)維,gdb,調(diào)試技巧

一、前言

  • 學(xué)習(xí)了【vim】知道了如何編輯一個代碼文本
  • 學(xué)習(xí)了【gcc】知道了如何編譯一個代碼文本
  • 學(xué)習(xí)了【make/Makefile】知道了如何自動化構(gòu)建一個代碼文本

但是如何對一段代碼去進(jìn)行調(diào)試呢,此時就要使用到Linux下的調(diào)試器gdb了。對于這個調(diào)試器來說,不像是VS中那樣的圖形化界面形式,而是采用純命令行的形式進(jìn)行調(diào)試??赡芪业闹v解會比較晦澀難懂,在學(xué)習(xí)的過程中主要是會一些gdb下基本的操作即可

二、調(diào)試版本與發(fā)布版本

1、見見gdb

下面是本次調(diào)試所要使用到的代碼

  1 #include <stdio.h>
  2 
  3 int AddToTop(int top)
  4 {
  5     printf("Enter AddToTop\n");
  6 
  7     int count = 0;
  8     for(int i = 1;i <= top; ++i)
  9     {
 10        count += i;
 11     }
 12 
 13     printf("Quit AddToTop\n");                                                                         
 14     return count;
 15 }
 16 
 17 int main(void)
 18 {
 19     int top = 100;
 20     int ret = AddToTop(top);
 21 
 22     printf("ret = %d\n", ret);
 23     return 0;
 24 }

下面是Makefile中的內(nèi)容,用于自動化編譯

  1 mytest:test.c
  2     gcc -o mytest test.c -std=c99                                                                      
  3 .PHONY:clean
  4 clean:
  5     rm -rf mytest

注:-std=c99表示以c99的標(biāo)準(zhǔn)來編譯代碼


  • 如果要進(jìn)入gdb開始調(diào)試,那直接gdb + 可執(zhí)行程序即可
  • 不過進(jìn)去之后發(fā)現(xiàn)似乎有一些奇怪的內(nèi)容,【no debugging symbols found】,翻譯過來就是沒有調(diào)試信息。那這是為何呢?是gdb出問題了嗎?

linux gdb調(diào)試命令,# Linux基礎(chǔ)入門篇,linux,運(yùn)維,gdb,調(diào)試技巧

  • 先不要著急,如果有經(jīng)常調(diào)試的同學(xué)就可以知道只有在【DeBug】的環(huán)境下才會有我們想要的調(diào)試信息,所以可以初步推斷這可能不是一個【DeBug】版本的可執(zhí)行程序
  • 先使用q(quit)退出gdb

讓我們先看下去,了解一下其他的知識再來解決這個問題

2、程序員與測試人員

接下去我們就來說說有關(guān)【DeBug】和【Release】版本的不同之處

??【Debug】—— 調(diào)試版本
??【Release】—— 發(fā)布版本

  • 在使用VS的時候我們可以直接使用鼠標(biāo)來進(jìn)行操作,當(dāng)前程序以DeBug或者是Release的形式進(jìn)行運(yùn)行,那么運(yùn)行出來的可執(zhí)行程序版本也是不同的,我們程序員在編寫代碼后運(yùn)行一般是使用【DeBug】環(huán)境進(jìn)行運(yùn)行。因為在企業(yè)里寫軟件項目,將代碼寫完后程序員自己要做簡單的測試,保證代碼沒有問題
  • 當(dāng)程序員自己測試完沒有問題之后,就會將這個可執(zhí)行程序給到測試人員進(jìn)行測試,而且會給出自己的單元測試報告。對于測試人員來說所處的模式是【Release】,也就是將來客戶要使用的這款軟件的發(fā)布版本
  • 當(dāng)測試在測的過程中,一定會發(fā)現(xiàn)一些問題。此時測試人員就會把報告再打回研發(fā)部。研發(fā)部做修改重新生成Release版本的可行性程序給到測試人員繼續(xù)測試
  • 最后只有當(dāng)測試通過了,再將生成的【單元測試報告】與產(chǎn)品經(jīng)理進(jìn)行核對之后沒有問題,那這個軟件才可以真正地面向市場??

3、為什么Release不能調(diào)試但DeBug可以調(diào)試?

其實對于我們剛才直接make自動化生成的可執(zhí)行程序是通過gcc直接編譯產(chǎn)生得到的,它是一個【Release】版本的可執(zhí)行程序,因此無法進(jìn)行調(diào)試

  • 若是我們想要使用gcc/g++去生成一個可執(zhí)行程序時,默認(rèn)是【Release】版本的,而不是【DeBug】
  • 但若是我們想要去生成一個【DeBug】版本的可執(zhí)行程序也是可以的,只需要修改一下我們的Makefile即可,給gcc后面帶上一個-g的命令選項,此時再去make一下的話生成的就是【DeBug】版本的了

  • 為了之前的【Release】版本不被覆蓋,我們將其重命名一下為mytest-release
  • 在生成【DeBug】版本后一樣對其進(jìn)行一個重命名為mytest-debug

linux gdb調(diào)試命令,# Linux基礎(chǔ)入門篇,linux,運(yùn)維,gdb,調(diào)試技巧

  • 通過觀察上圖中兩個可執(zhí)行文件的大小便可以發(fā)現(xiàn)雖然它們都是可執(zhí)行程序,但是容量大小卻不一樣,這是為什么呢?

  • 因為以Release版本發(fā)布的軟件是給客戶的,客戶是不需要調(diào)試信息

  • 往可執(zhí)行程序里添加很多的調(diào)試信息意味著軟件的體積會變大

    • 一方面,用戶下載需要時間了
    • 另一方面,用戶下載好之后將軟件啟動、運(yùn)行都需要更多的時間,體驗不好。一般能不加就不加
  • 但是對于DeBug來說會自動加調(diào)試信息,容量體積比Release大

但是就這么說說太抽象了,我們得看看這個可執(zhí)行文件里的調(diào)試信息究竟是怎樣的??

readelf -S mytest-debug
  • 在C生萬物 | 程序環(huán)境和預(yù)處理中,我有說到過對于【可執(zhí)行文件】它是一個二進(jìn)制文件,若是查看它的源碼就可以發(fā)現(xiàn)里面都是一堆亂碼

linux gdb調(diào)試命令,# Linux基礎(chǔ)入門篇,linux,運(yùn)維,gdb,調(diào)試技巧

當(dāng)我們面對一堆二進(jìn)制亂碼措手不及的時候,給大家提到過一個東西叫做readelf,其實它是Linux中的一個指令,可以用來讀取【elf】格式的文件

  • 加上-S的命令選項以符號表的形式來進(jìn)行讀取這個文件,就以一個列表的形式展現(xiàn)出了這個帶調(diào)試信息的可執(zhí)行程序
  • 下面展現(xiàn)幾個比較常見的。例如這里的
    • .rodata就是read only data即只讀全局?jǐn)?shù)據(jù)區(qū)
    • .data就是已初始化全局?jǐn)?shù)據(jù)區(qū)
    • .bss就是未初始化全局?jǐn)?shù)據(jù)區(qū)

linux gdb調(diào)試命令,# Linux基礎(chǔ)入門篇,linux,運(yùn)維,gdb,調(diào)試技巧

  • 不過這些呢是這個可執(zhí)行文件中的所有內(nèi)容,若是我們只是先要查看一些debug的調(diào)試信息,就要對這些東西進(jìn)行一個篩選才行
  • 此時就可以使用到grep命令來進(jìn)行一個篩選。便可以查看到所有的debug調(diào)試信息了

linux gdb調(diào)試命令,# Linux基礎(chǔ)入門篇,linux,運(yùn)維,gdb,調(diào)試技巧

  • 上面是查看【DeBug】版本下的調(diào)試信息,在【Release】版本有沒有呢
  • 我們也是讀取并搜尋一下這個文件便可以發(fā)現(xiàn)對于【Release】版本來說是不存在調(diào)試信息的,所以什么都沒有被打印出來

linux gdb調(diào)試命令,# Linux基礎(chǔ)入門篇,linux,運(yùn)維,gdb,調(diào)試技巧
【總結(jié)一下】

  • 程序的發(fā)布方式有兩種,debug模式和release模式
  • Linux gcc/g++出來的二進(jìn)制程序,默認(rèn)是release模式
  • 要使用gdb調(diào)試,必須在源代碼生成二進(jìn)制程序的時候, 加上-g選項

好,說到這里,對于調(diào)試相關(guān)背景就全部講完了,接下去我們正式進(jìn)入【gdb】的學(xué)習(xí)??

三、使用gdb調(diào)試代碼

1、指令集匯總

因為這個調(diào)試器是在Linux環(huán)境下的,是純命令行模式,所以會有很多的指令,做好心里準(zhǔn)備??

注:()括號里面是該指令的全稱

  • l(list) 行號/函數(shù)名 —— 顯示對應(yīng)的code,每次10行

  • r(run) —— F5【無斷點直接運(yùn)行、有斷點從第一個斷點處開始運(yùn)行】

  • b(breakpoint) + 行號 —— 在那一行打斷點

  • b 源文件:函數(shù)名 —— 在該函數(shù)的第一行打上斷點

  • b 源文件:行號 —— 在該源文件中的這行加上一個斷點吧

  • info b —— 查看斷點的信息

    breakpoint already hit 1 time【此斷點被命中一次】

  • d(delete) + 當(dāng)前要刪除斷點的編號 —— 刪除一個斷點【不可以d + 行號】

    • 若當(dāng)前沒有跳出過gdb,則斷點的編號會持續(xù)累加
  • d + breakpoints —— 刪除所有的斷點

  • disable b(breakpoints) —— 使所有斷點無效【默認(rèn)缺省】

  • enable b(breakpoints) —— 使所有斷點有效【默認(rèn)缺省】

  • disable b(breakpoint) + 編號 —— 使一個斷點無效【禁用斷點】

  • enable b(breakpoint) + 編號 —— 使一個斷點有效【開啟斷點】

    • 相當(dāng)于VS中的空斷點
  • enable breakpount —— 使一個斷點有效【開啟斷電】

  • n(next) —— 逐過程【相當(dāng)于F10,為了查找是哪個函數(shù)出錯了】

  • s(step) —— 逐語句【相當(dāng)于F11,】

  • bt —— 看到底層函數(shù)調(diào)用的過程【函數(shù)壓?!?/p>

  • set var —— 修改變量的值

  • p(print) 變量名 —— 打印變量值

  • display —— 跟蹤查看一個變量,每次停下來都顯示它的值【變量/結(jié)構(gòu)體…】

  • undisplay + 變量名編號 —— 取消對先前設(shè)置的那些變量的跟蹤

排查問題三劍客??

  • until + 行號 —— 進(jìn)行指定位置跳轉(zhuǎn),執(zhí)行完區(qū)間代碼
  • finish —— 在一個函數(shù)內(nèi)部,執(zhí)行到當(dāng)前函數(shù)返回,然后停下來等待命令
  • c(continue) —— 從一個斷點處,直接運(yùn)行至下一個斷點處【VS下不斷按F5】

2、命令演示

看了上面的這些命令后,相信你一定回到了剛開始學(xué)習(xí)Linux指令的時候那種恐懼感,不過沒關(guān)系,我會一一地演示這些指令,讓你在看完本文后有一個基本的調(diào)試能力??

  • 首先我們進(jìn)入到gdb,然后它會等待我們輸入指令

linux gdb調(diào)試命令,# Linux基礎(chǔ)入門篇,linux,運(yùn)維,gdb,調(diào)試技巧

? 行號顯示

l(list) 行號/函數(shù)名 —— 顯示對應(yīng)的code,每次10行

  • 首先若是直接【L】的話便會隨機(jī)顯示出該源文件中的隨機(jī)10行內(nèi)容,這不是我們想要的

linux gdb調(diào)試命令,# Linux基礎(chǔ)入門篇,linux,運(yùn)維,gdb,調(diào)試技巧

  • 若是【L 0】或者是【L 1】的話那就是從第一行開始往下列10行的內(nèi)容
    • 注意這里的L是小寫,而且與數(shù)字之間要有一個空格

linux gdb調(diào)試命令,# Linux基礎(chǔ)入門篇,linux,運(yùn)維,gdb,調(diào)試技巧

  • 接下去若是想要看到我們所寫的全部代碼,只需要多Enter幾次就可以了,gdb會自動記憶你上次敲入的指令

linux gdb調(diào)試命令,# Linux基礎(chǔ)入門篇,linux,運(yùn)維,gdb,調(diào)試技巧

? 斷點設(shè)置

b + 行號 —— 在那一行打斷點

linux gdb調(diào)試命令,# Linux基礎(chǔ)入門篇,linux,運(yùn)維,gdb,調(diào)試技巧
b 源文件:函數(shù)名 —— 在該函數(shù)的第一行打上斷點

linux gdb調(diào)試命令,# Linux基礎(chǔ)入門篇,linux,運(yùn)維,gdb,調(diào)試技巧

b 源文件:行號 —— 在該源文件中的這行加上一個斷點

linux gdb調(diào)試命令,# Linux基礎(chǔ)入門篇,linux,運(yùn)維,gdb,調(diào)試技巧

? 查看斷點信息

info b —— 查看斷點的信息

  • 若是直接執(zhí)行【info】的話,出來的就是所有的調(diào)試信息

linux gdb調(diào)試命令,# Linux基礎(chǔ)入門篇,linux,運(yùn)維,gdb,調(diào)試技巧

  • 但若是我們只想查看一下所打的斷點的信息,那就在后面加個b/breakpoint

linux gdb調(diào)試命令,# Linux基礎(chǔ)入門篇,linux,運(yùn)維,gdb,調(diào)試技巧
來簡要介紹一下斷點的一些字段信息

  • Num —— 編號
  • Type —— 類型
  • Disp —— 狀態(tài)
  • Enb —— 是否可用
  • Address —— 地址
  • What —— 在此文件的哪個函數(shù)的第幾行

linux gdb調(diào)試命令,# Linux基礎(chǔ)入門篇,linux,運(yùn)維,gdb,調(diào)試技巧

  • 最后的話就是每個斷點信息的下面這塊breakpoint already hit 1 time即此斷點被命中1次

? 刪除斷點

d + 當(dāng)前要刪除斷點的編號 —— 刪除一個斷點【不可以d + 行號】

linux gdb調(diào)試命令,# Linux基礎(chǔ)入門篇,linux,運(yùn)維,gdb,調(diào)試技巧
d + breakpoints —— 刪除所有的斷點

linux gdb調(diào)試命令,# Linux基礎(chǔ)入門篇,linux,運(yùn)維,gdb,調(diào)試技巧

  • 此時若繼續(xù)將這個20行的斷點打上時,就可以發(fā)現(xiàn)其編號為【4】,而并不是從1開始,這是因為我們沒有退出過gdb,所以會持續(xù)上一次的編號繼續(xù)往下

linux gdb調(diào)試命令,# Linux基礎(chǔ)入門篇,linux,運(yùn)維,gdb,調(diào)試技巧

? 開啟 / 禁用斷點

disable b(breakpoints) —— 使所有斷點無效【默認(rèn)缺省】

linux gdb調(diào)試命令,# Linux基礎(chǔ)入門篇,linux,運(yùn)維,gdb,調(diào)試技巧
enable b(breakpoints) —— 使所有斷點有效【默認(rèn)缺省】

linux gdb調(diào)試命令,# Linux基礎(chǔ)入門篇,linux,運(yùn)維,gdb,調(diào)試技巧
disable b(breakpoint) + 編號 —— 使一個斷點無效【禁用斷點】

linux gdb調(diào)試命令,# Linux基礎(chǔ)入門篇,linux,運(yùn)維,gdb,調(diào)試技巧
enable b(breakpoint) + 編號 —— 使一個斷點有效【開啟斷點】

linux gdb調(diào)試命令,# Linux基礎(chǔ)入門篇,linux,運(yùn)維,gdb,調(diào)試技巧

其實對于禁用斷點和啟用斷點,VS中也是有的,它叫做【空斷點】。我們一起來看看

linux gdb調(diào)試命令,# Linux基礎(chǔ)入門篇,linux,運(yùn)維,gdb,調(diào)試技巧
linux gdb調(diào)試命令,# Linux基礎(chǔ)入門篇,linux,運(yùn)維,gdb,調(diào)試技巧

? 運(yùn)行 / 調(diào)試

r(run) —— F5【無斷點直接運(yùn)行、有斷點從第一個斷點處開始運(yùn)行】

  • 首先若是將斷點刪除掉,使用【r】指令運(yùn)行的話就會直接運(yùn)行到程序結(jié)束

linux gdb調(diào)試命令,# Linux基礎(chǔ)入門篇,linux,運(yùn)維,gdb,調(diào)試技巧

  • 再加上斷點去運(yùn)行的話就會在打的斷點處停下來

linux gdb調(diào)試命令,# Linux基礎(chǔ)入門篇,linux,運(yùn)維,gdb,調(diào)試技巧

? 逐過程和逐語句

n(next) —— 逐過程【相當(dāng)于F10,為了查找是哪個函數(shù)出錯了】

  • 可以看到,我從第一個斷點處也就是20行的位置開始執(zhí)行,按下【n】之后因為在其后即22行有一個斷點,此時就會直接運(yùn)行到斷點處

linux gdb調(diào)試命令,# Linux基礎(chǔ)入門篇,linux,運(yùn)維,gdb,調(diào)試技巧
s(step) —— 逐語句【相當(dāng)于F11,一次走一條代碼,可進(jìn)入函數(shù),同樣的庫函數(shù)也會進(jìn)入】

  • 此時我們按下【s】,也就相當(dāng)于是【step】,讓程序一步一步地走,繼而進(jìn)入了AddToTop這個函數(shù),若是你在printf()語句要執(zhí)行時按下【s】的話gdb就會進(jìn)入printf()庫函數(shù)內(nèi)部去執(zhí)行,這里就不展示了

linux gdb調(diào)試命令,# Linux基礎(chǔ)入門篇,linux,運(yùn)維,gdb,調(diào)試技巧

  • 接下去我們可以就繼續(xù)【n】,然后進(jìn)行逐過程調(diào)試,來到for循環(huán)中,那么逐過程也就是變量i的累加和計數(shù)器count的累加,所以會反復(fù)執(zhí)行(通過圖中最左側(cè)可以看出是第8行和第10行在反復(fù)執(zhí)行
  • 可以看到后面我沒有再按【n】了,但是依舊會執(zhí)行上面的步驟,這點上面也有提到過,因為gdb會自動化記憶你上一次執(zhí)行過的命令,所以若是不想再敲了,直接Enter就可以了

linux gdb調(diào)試命令,# Linux基礎(chǔ)入門篇,linux,運(yùn)維,gdb,調(diào)試技巧

? 打印 / 追蹤變量

p(print) 變量名 —— 打印變量值

  • 都執(zhí)行了那么多次了,不知道【i】和【count】發(fā)生了怎樣的變化,將它們打印出來看看吧??

linux gdb調(diào)試命令,# Linux基礎(chǔ)入門篇,linux,運(yùn)維,gdb,調(diào)試技巧

  • 通過繼續(xù)執(zhí)行【n】,然后再去打印就可以發(fā)現(xiàn)i的值和count的值發(fā)生了變化

linux gdb調(diào)試命令,# Linux基礎(chǔ)入門篇,linux,運(yùn)維,gdb,調(diào)試技巧

但是你不覺得這樣每次去打印會顯得很繁瑣嗎,那一定會的,所以我們有更好的辦法??

display —— 跟蹤查看一個變量,每次停下來都顯示它的值【變量/結(jié)構(gòu)體…】

linux gdb調(diào)試命令,# Linux基礎(chǔ)入門篇,linux,運(yùn)維,gdb,調(diào)試技巧

  • 我們也可以去追蹤一下這兩個變量的地址,不過可以看到對于地址來說是不會發(fā)生改變的

linux gdb調(diào)試命令,# Linux基礎(chǔ)入門篇,linux,運(yùn)維,gdb,調(diào)試技巧
undisplay + 變量名編號 —— 取消對先前設(shè)置的那些變量的跟蹤

  • 但是呢,每次都追蹤打印這么多內(nèi)容又太多了,我想把它們?nèi)∠丝梢詥??答?strong>當(dāng)然是可以的
  • 既然有display,那就有undisplay

linux gdb調(diào)試命令,# Linux基礎(chǔ)入門篇,linux,運(yùn)維,gdb,調(diào)試技巧

? 查看函數(shù)調(diào)用

bt —— 看到底層函數(shù)調(diào)用的過程【函數(shù)壓?!?/strong>

  • 通過仔細(xì)觀察剛才追蹤的4個變量最左側(cè)的編號,就可以看到它們的排列的順序是倒著的。因為變量i和變量count是我們先追蹤的,它們的地址是我們后追蹤的,所以可以看出這很像是一個壓棧的過程

linux gdb調(diào)試命令,# Linux基礎(chǔ)入門篇,linux,運(yùn)維,gdb,調(diào)試技巧

  • 其實不僅是對于它們,AddToTop函數(shù)和main函數(shù)也呈現(xiàn)這樣的關(guān)系。此時我們就可以通過【bt】這個指令來查看函數(shù)壓棧的過程,此時便可以看到因為

linux gdb調(diào)試命令,# Linux基礎(chǔ)入門篇,linux,運(yùn)維,gdb,調(diào)試技巧

? 修改變量的值

set var —— 修改變量的值

  • 對于這個修改變量的值,很像是在VS里調(diào)試之前設(shè)置的那種條件斷點,可以使調(diào)試開始后直接運(yùn)行到此斷點處。不過對于【set var】而言是在調(diào)試過程中進(jìn)行設(shè)置

linux gdb調(diào)試命令,# Linux基礎(chǔ)入門篇,linux,運(yùn)維,gdb,調(diào)試技巧

我們也可以到VS中來看一下條件斷點是如何設(shè)置的

在右擊選擇【條件】后,就可以輸入你本次執(zhí)行代碼想要從哪個條件開始,然后按下Enter,啟動調(diào)試之后就會從你設(shè)置的條件處開始執(zhí)行

linux gdb調(diào)試命令,# Linux基礎(chǔ)入門篇,linux,運(yùn)維,gdb,調(diào)試技巧

排查問題三劍客??

掌握了上面的這些,你就可以在Linux下調(diào)一些簡單的代碼了,不過想做到高效地進(jìn)行調(diào)試,就需要學(xué)習(xí)一下【三劍客】

? 指定行號跳轉(zhuǎn)

until + 行號 —— 進(jìn)行指定位置跳轉(zhuǎn),執(zhí)行完區(qū)間代碼

  • 可以看到,當(dāng)前在for循環(huán)內(nèi)容執(zhí)行累加的邏輯,但若是我們一直這么執(zhí)行下去,就沒有時間排錯了,除了上面的哪一種【set var】之外,還有一種方法其實起到直接結(jié)束當(dāng)前循環(huán)的作用,那就是進(jìn)行指定行號跳轉(zhuǎn)
  • 通過觀察下圖可以看到,當(dāng)我們運(yùn)行了until 13之后,程序直接就給出了我們最終的結(jié)果count,而且即將要執(zhí)行最后的打印語句,說明我們跳轉(zhuǎn)成功了

linux gdb調(diào)試命令,# Linux基礎(chǔ)入門篇,linux,運(yùn)維,gdb,調(diào)試技巧

  • 不過呢,在我使用這個【until】的時候,遇到了一個bug,此時我在循環(huán)內(nèi)部,也就是第10行的位置打了一個斷點,用過VS調(diào)試器的都知道一直按F5就可以立即執(zhí)行下一次循環(huán)。
  • 我在上面是沒有打上斷點的,所以使用【until】的時候也沒有出現(xiàn)問題,但是在下面我在循環(huán)內(nèi)部設(shè)置了一個斷點,此時再去使用【until 13】進(jìn)行跳轉(zhuǎn)的時候就出現(xiàn)問題了,并沒有馬上跳轉(zhuǎn)到指定的行號,而是接著執(zhí)行循環(huán)中的內(nèi)容

linux gdb調(diào)試命令,# Linux基礎(chǔ)入門篇,linux,運(yùn)維,gdb,調(diào)試技巧

? 強(qiáng)制執(zhí)行函數(shù)

finish —— 在一個函數(shù)內(nèi)部,執(zhí)行到當(dāng)前函數(shù)返回,然后停下來等待命令

  • 有時候我們會有這樣的需求,在初步排查的時候推斷可能是某個函數(shù)內(nèi)部的邏輯出了問題,但是呢又不想一步步地進(jìn)到函數(shù)內(nèi)部進(jìn)行調(diào)試,在VS中其實很簡單,只需要在函數(shù)下方設(shè)個斷點,然后F5直接運(yùn)行到斷點處即可
  • 但是在Linux下的gdb中,我們可以使用【finsh】指令來直接使一個函數(shù)執(zhí)行完畢。從下圖我們可以看到,首先【s】進(jìn)到函數(shù)內(nèi)部,接下去我直接使用finish,可以看到它直接回到了調(diào)用函數(shù)的位置,returned了一個返回值

linux gdb調(diào)試命令,# Linux基礎(chǔ)入門篇,linux,運(yùn)維,gdb,調(diào)試技巧

  • 然后可以看到,在獲取到返回值后,也就直接進(jìn)行了printf打印

linux gdb調(diào)試命令,# Linux基礎(chǔ)入門篇,linux,運(yùn)維,gdb,調(diào)試技巧

? 跳轉(zhuǎn)到下一斷點

c(continue) —— 從一個斷點處,直接運(yùn)行至下一個斷點處【VS下不斷按F5】

  • 這點也是我剛才在上面有提到過的,在VS中,我們要直接跳轉(zhuǎn)到下一個斷點處只修要按下F5即可,那在gdb中該如何操作呢,你需要敲個【c】就可以了
  • 從下圖我們可以看出,對于這個指令的用處可謂是非常大,當(dāng)我處于第一個斷點也就是20行的時候,直接敲下【c】,就可以運(yùn)行到第二個斷點處也就是第10行。之后若反復(fù)敲【c】,因為這是一個單語句的循環(huán),所以循環(huán)的下一次還是會執(zhí)行到此處。上面的這兩個功能就和我們在VS中用的F5是一個道理

linux gdb調(diào)試命令,# Linux基礎(chǔ)入門篇,linux,運(yùn)維,gdb,調(diào)試技巧

四、實戰(zhàn)演練:Swap Two Numbers

??紙上得來終覺淺,絕知此事要躬行??
————————————

以下是本次調(diào)試所要使用到的代碼,相信你一定非常熟悉了,也就是使用指針交換兩數(shù),如果想看細(xì)節(jié)講解可以看看我的函數(shù)章節(jié)

  1 #include <stdio.h>
  2 
  3 void swap(int* x, int* y)
  4 {
  5     int t = *x;
  6     *x = *y;
  7     *y = t;                                                                                            
  8 }
  9 int main(void)
 10 {
 11     int a = 10;
 12     int b = 20;
 13 
 14     printf("a = %d, b = %d\n", a, b);
 15 
 16     swap(&a, &b);
 17 
 18     printf("a = %d, b = %d\n", a, b);
 19     return 0;
 20 }

  • 首先我們在程序第16行設(shè)置上一個斷點,然后【r】從第15行開始運(yùn)行

linux gdb調(diào)試命令,# Linux基礎(chǔ)入門篇,linux,運(yùn)維,gdb,調(diào)試技巧

  • 然后我們使用【s】進(jìn)入到swap函數(shù)中,因為我首先不想調(diào)試,想先立馬看看運(yùn)行結(jié)果,但是此時又已經(jīng)進(jìn)入調(diào)試了,那么我們就可以使用到【finish】來立馬執(zhí)行完這個函數(shù),然后觀察一下結(jié)果
  • 可以看到,最后打印出結(jié)果的時候a和b的值確實發(fā)生了交換

linux gdb調(diào)試命令,# Linux基礎(chǔ)入門篇,linux,運(yùn)維,gdb,調(diào)試技巧

  • 既然清楚了二者會進(jìn)行一個交換,接下去我們就逐語句【n】進(jìn)行一個單步追蹤吧
  • 因為提前看了執(zhí)行結(jié)果,所以我們要重新開始調(diào)試,按下【r】即可,它會詢問你是否需要重新開始調(diào)試,選擇y之后就可以重新從16行開始進(jìn)行調(diào)試

linux gdb調(diào)試命令,# Linux基礎(chǔ)入門篇,linux,運(yùn)維,gdb,調(diào)試技巧

  • 首先通過【display】記錄一下兩個變量的值和地址

linux gdb調(diào)試命令,# Linux基礎(chǔ)入門篇,linux,運(yùn)維,gdb,調(diào)試技巧

  • 接著按【s】進(jìn)入到swap函數(shù)里,追蹤一下指針x和指針y的內(nèi)容,也就是它們所存放的地址,就可以看到,函數(shù)內(nèi)部已經(jīng)接受到了這兩個變量的地址

linux gdb調(diào)試命令,# Linux基礎(chǔ)入門篇,linux,運(yùn)維,gdb,調(diào)試技巧

  • 但是我們后面不想再查看它們了,只需要看值是否被修改,此時就可以取消對它們的跟蹤【undisplay】

linux gdb調(diào)試命令,# Linux基礎(chǔ)入門篇,linux,運(yùn)維,gdb,調(diào)試技巧

  • 然后對我們要觀察的值變化繼續(xù)做一個追蹤
  • 并且在執(zhí)行完第一個語句t = *x時,臨時變量t中已經(jīng)存放了變量a的值,也就是指針?biāo)赶虻哪菈K空間中的值

linux gdb調(diào)試命令,# Linux基礎(chǔ)入門篇,linux,運(yùn)維,gdb,調(diào)試技巧

  • 接下去執(zhí)行*x = *y,此時*x中的值就發(fā)生了變化,因為指針x可以直接找到變量a的地址,所以可以對其中的內(nèi)容做修改,就變?yōu)榱?0

linux gdb調(diào)試命令,# Linux基礎(chǔ)入門篇,linux,運(yùn)維,gdb,調(diào)試技巧

  • 接下去執(zhí)行*y = t,同理,指針y可以直接找到變量b的地址,所以可以對其中的內(nèi)容做修改,將原本保存在臨時變量t中的10賦值給到*y,也就修改了其中的內(nèi)容

linux gdb調(diào)試命令,# Linux基礎(chǔ)入門篇,linux,運(yùn)維,gdb,調(diào)試技巧

  • 再按【n】的話這個swap函數(shù)就執(zhí)行結(jié)束了,回到了main函數(shù),就可以清楚地看到函數(shù)內(nèi)部的修改帶動了函數(shù)外部值的變化,真正地通過【傳址調(diào)用】交換了兩個數(shù)

linux gdb調(diào)試命令,# Linux基礎(chǔ)入門篇,linux,運(yùn)維,gdb,調(diào)試技巧

敲黑板:重點來了

  • 但是我不僅想讓你看到這些,更加重要的一點不知你有沒有發(fā)現(xiàn),剛才我們在main函數(shù)中追蹤的變量a和變量b的值與地址,到了swap()中就不見了,這是為什么呢?
  • 其實就是因為兩個函數(shù)的函數(shù)棧幀不同,變量a和變量b位于main函數(shù)的函數(shù)棧幀中;而指針變量x和指針變量y位于swap函數(shù)的函數(shù)棧幀中,是互不相干的,臨時變量除了函數(shù)棧幀就會被銷毀【如果聽不懂這些請看反匯編深挖【函數(shù)棧幀】的創(chuàng)建和銷毀】
  • 但是因為在swap()內(nèi)部接受到了外部兩個變量的地址,所以在函數(shù)內(nèi)部就可以通過這兩個指針找到這兩個變量的地址,從而對這兩個空間中的內(nèi)容做一個修改的操作

通過以上的實驗演練,你是否對調(diào)試器GDB的使用更上一層樓??

五、總結(jié)與提煉

最后來總結(jié)一下本文所學(xué)習(xí)的內(nèi)容??

  • 在本文的開始,我們在初見GDB的時候發(fā)現(xiàn)了【no debugging symbols】的報錯信息,于是便談到了一個可執(zhí)行程序的【DeBug】版本和【Release】版本,知道了對于前者來說是我們程序員使用的環(huán)境,是存在調(diào)試信息的;對于后者來說是測試人員所處的環(huán)境,是不存在調(diào)試信息的。而對于gcc/g++而言默認(rèn)生成的可執(zhí)行程序就是【Release】版本的,因此我們要加上一個-g命令選項使其在make之后生成一個【DeBug】版本的可執(zhí)行程序,這樣就可以進(jìn)行調(diào)試了
  • 接著我們正式進(jìn)入到了調(diào)試器GDB的使用,介紹了很多相關(guān)的指令,這些都是我整理出來的常見指令,其實對于GDB來說還有很多指令,但是真正常用的也就這些,只要你認(rèn)真地看下來,將它們都使用熟練了,相信你的調(diào)試功底會大幅度提升,對你在VS中的調(diào)試也是有所幫助的
  • 最后,在學(xué)習(xí)了GDB的許多調(diào)試指令后,我們便進(jìn)行了【Swap Two Numbers】的實戰(zhàn)演練,不僅鞏固了C語言中有關(guān)傳址調(diào)用以及函數(shù)棧幀的相關(guān)指知識,而且使我們對于調(diào)試器GDB的使用更上一層樓↑

以上就是本文要介紹的所有內(nèi)容,感謝您的閱讀??

linux gdb調(diào)試命令,# Linux基礎(chǔ)入門篇,linux,運(yùn)維,gdb,調(diào)試技巧文章來源地址http://www.zghlxwxcb.cn/news/detail-784469.html

到了這里,關(guān)于Linux | 調(diào)試器GDB的詳細(xì)教程【純命令行調(diào)試】的文章就介紹完了。如果您還想了解更多內(nèi)容,請在右上角搜索TOY模板網(wǎng)以前的文章或繼續(xù)瀏覽下面的相關(guān)文章,希望大家以后多多支持TOY模板網(wǎng)!

本文來自互聯(lián)網(wǎng)用戶投稿,該文觀點僅代表作者本人,不代表本站立場。本站僅提供信息存儲空間服務(wù),不擁有所有權(quán),不承擔(dān)相關(guān)法律責(zé)任。如若轉(zhuǎn)載,請注明出處: 如若內(nèi)容造成侵權(quán)/違法違規(guī)/事實不符,請點擊違法舉報進(jìn)行投訴反饋,一經(jīng)查實,立即刪除!

領(lǐng)支付寶紅包贊助服務(wù)器費用

相關(guān)文章

  • Linux調(diào)試器gdb

    Linux調(diào)試器gdb

    本文已收錄至《 Linux知識與編程 》專欄! 作者: ARMCSKGT 演示環(huán)境: CentOS 7? ?? ? 目錄 前言 正文 下載gdb 生成可調(diào)式文件 進(jìn)入gdb gdb常用指令 查看代碼 l? 運(yùn)行程序 r? 斷點設(shè)置 b? 顯示信息 info? 查看斷點 info b? 刪除斷點?d? 禁用斷點 disable breakpoints? 啟用斷點 enable brea

    2024年02月14日
    瀏覽(21)
  • [Linux] Linux代碼調(diào)試器 -- gdb

    [Linux] Linux代碼調(diào)試器 -- gdb

    1、程序的發(fā)布方式有兩種,debug模式和release模式 2、Linux gcc/g++出來的二進(jìn)制程序,默認(rèn)是release模式 3、要使用gdb調(diào)試,必須在源代碼生成二進(jìn)制程序的時候, 加上 -g 選項 我們先來寫一段C語言代碼: 這里我們正常再編寫一個Makefile文件,用于自動化構(gòu)建,我們要還是正常的編

    2024年02月05日
    瀏覽(28)
  • 【Linux】Linux調(diào)試器-gdb使用

    【Linux】Linux調(diào)試器-gdb使用

    程序的發(fā)布方式有兩種,debug模式和release模式 Linux gcc/g++出來的二進(jìn)制程序,默認(rèn)是release模式 要使用gdb調(diào)試,必須在源代碼生成二進(jìn)制程序的時候, 加上 -g 選項 退出:? 調(diào)試命令: list/l 行號:顯示binFile源代碼,接著上次的位置往下列,每次列10行。 list/l 函數(shù)名:列出某

    2024年02月21日
    瀏覽(27)
  • Linux調(diào)試器之gdb

    Linux調(diào)試器之gdb

    我們前面介紹了幾個基本的環(huán)境開發(fā)工具。例如通過yum我們可以安裝和卸載軟件、通過vim我們可以寫代碼、通過gcc和g++我們可以編譯代碼成可執(zhí)行程序。但是如何在Linux下調(diào)試代碼呢?我們并未介紹,本期我們將來介紹最后一個工具 --- 調(diào)試器gdb。 程序的發(fā)布方式 gdb基本的調(diào)

    2024年04月16日
    瀏覽(37)
  • Linux - 還不懂 gdb 調(diào)試器?(調(diào)試軟件)

    Linux - 還不懂 gdb 調(diào)試器?(調(diào)試軟件)

    當(dāng)前,我們可以使用 make/makefile 來程序化執(zhí)行代碼文件;可以使用 gcc/g++ 等編譯器來編譯代碼;可以使用 vim 編輯器來編寫代碼;其實在 Linux 當(dāng)中還有一個工具,可以實現(xiàn)調(diào)試工作,這個工具就是 -- gdb。 在了解調(diào)試器之前,你應(yīng)該對代碼的發(fā)布版本做一些了解: 我們在 VS

    2024年02月07日
    瀏覽(21)
  • 【Linux】——調(diào)試器-gdb的使用

    【Linux】——調(diào)試器-gdb的使用

    序言: 本期,我將帶領(lǐng)大家學(xué)習(xí)的關(guān)于linux下的 調(diào)試器gdb 的使用,廢話不多說跟著我一起去看看吧??! 目錄 前言 (一)背景介紹 1、debug模式和release模式 2、為什么Release不能調(diào)試但DeBug可以調(diào)試 3、初步見識 1??readelf (二)調(diào)試代碼 1、命名大全 2、具體演示 0??行號顯

    2024年02月07日
    瀏覽(23)
  • 【Linux】gdb調(diào)試器的使用

    【Linux】gdb調(diào)試器的使用

    文章目錄 一、gdb簡介 二、調(diào)試前的準(zhǔn)備 1、生成調(diào)試文件 2、啟動 gdb? 三、gdb 使用方法? 1、查看源代碼 2、設(shè)置 / 查看斷點(多種方式設(shè)置斷點) 方法一 方法二 方法三 3、run? 4、刪除斷點、斷點無效 5、逐過程調(diào)試(以函數(shù)為單位) 6、逐語句調(diào)試 7、查看調(diào)用鏈 8、查看變

    2024年02月02日
    瀏覽(36)
  • 【Linux】Linux下調(diào)試器gdb的使用

    【Linux】Linux下調(diào)試器gdb的使用

    ??作者主頁:@安 度 因 ??學(xué)習(xí)社區(qū):StackFrame ??專欄鏈接:Linux 如果無聊的話,就來逛逛 我的博客棧

    2024年02月19日
    瀏覽(29)
  • 【Linux】調(diào)試器:gdb 的基本使用

    gdb 全稱 GNU symbolic debugger,是 Linux 下常用的程序調(diào)試器。 調(diào)試器的核心工作,主要是為了定位問題。廢話不多說。 gdb 的安裝 另外: gcc、g++ 默認(rèn)形成的版本是 release,不是 debug 版本!所以想要在 Linux 下調(diào)試程序,需要在 Makefile 文件 中,添加 -g 選項 指定以 dubug 方式編譯程

    2024年02月16日
    瀏覽(23)
  • Linux開發(fā)工具之調(diào)試器gdb

    程序的發(fā)布方式有兩種,debug模式和release模式 Linux gcc/g++出來的二進(jìn)制程序,默認(rèn)是release模式 要使用gdb調(diào)試,必須在源代碼生成二進(jìn)制程序的時候, 加上 -g 選項 ? 所以一份代碼若要被調(diào)試必須是debug模式,但是在linux下我們編譯代碼的時候默認(rèn)為release模式,要想讓我們的代碼

    2024年02月07日
    瀏覽(22)

覺得文章有用就打賞一下文章作者

支付寶掃一掃打賞

博客贊助

微信掃一掃打賞

請作者喝杯咖啡吧~博客贊助

支付寶掃一掃領(lǐng)取紅包,優(yōu)惠每天領(lǐng)

二維碼1

領(lǐng)取紅包

二維碼2

領(lǐng)紅包