【Linux學習】GDB調試器基本命令必知必會(一)

來源:互聯網
上載者:User

本文介紹Linux下GDB調試器常用的基本命令。

測試均在Ubuntu12.10下完成。

先看看GDB調試的:


對應的原始碼:

//插入排序,GDB調試測試代碼#include <stdio.h>int x[10],//存放輸入資料        y[10],//工作空間數組        num_inputs,//輸入數組長度        num_y = 0;//y中當前元素個數//函數//功能:從參數中提取輸入資料void get_args(int ac,char **av){        int i;        num_inputs = ac - 1;        for(i = 0;i < num_inputs;++i)                x[i] = atoi(av[i + 1]);}//函數//功能:向右移動工作數組中索引jj及其後面的所有元素void scoot_over(int jj){        int k;        for(k = num_y;k > jj;++k)                y[k] = y[k - 1];}//函數://功能:插入一個資料void insert(int new_y){        int j;        //工作數組為空白        if(0 == num_y){                y[0] = new_y;                return;        }        //將新元素插入到適當位置:第一個比new_y大的元素前面        for(j = 0;j < num_y;++j){                if(new_y < y[j]){                        //向右移動y[j]後面的所有元素                        scoot_over(j);                        y[j] = new_y;                        return;                }        }}//函數://功能:處理所有輸入資料void process_data(){        for(num_y = 0;num_y < num_inputs;++num_y)                insert(x[num_y]);}//函數://列印結果資料void print_results(){        int i;        for(i = 0;i < num_inputs;++i)                printf("%d\n",y[i]);}int main(int argc,char **argv){        get_args(argc,argv);        process_data();        print_results();}

原始碼編譯:gcc -g -Wall -o insert_sort ins.c這裡面一個必要的步驟是:GCC的-g選項:讓編譯器將符號表(對應於程式的變數和程式碼的記憶體位址列表)儲存在產生的可執行檔中。這樣才能在偵錯工作階段過程中引用原始碼中的變數名和行號。一些基本命令啟動GDB:gdb exeFileNamegdb中中文顯示是亂碼,暫時還不知道怎麼支援中文。線上說明,可以通過help命令訪問文檔:(gdb) help breakpoints以TUI模式運行GDB:在調用gdb的時候指定-tui選項或者在處於非TUI模式時在GDB中使用Ctrl+X+A按鍵組合,可以將終端螢幕分成原文字視窗和控制台的多個子視窗退出GDB:quit或者Ctrl+d可以直接按下斷行符號再次執行最近執行過的那條命令執行程式:run查看棧幀:frame num(棧幀編號)注意棧幀編號規則,當前正在執行的函數的幀被編號為0,其父幀(即該函數的調用者的棧幀)被編號為1,父幀的父幀被編號為2,以此類推。跳到調用棧中的下一個父幀:up引向相反方向:down顯示整個棧,即當前存在的所有幀的集合:backtrace滾動查看代碼:↑等方向鍵輸出當前值:print或者p瀏覽以前的GDB命令:上一個Ctrl+P、下一個Ctrl+N注意:如果我們需要修改程式,並且重新編譯,不必重啟GDB。GDB會在運行程式之前自動重新載入新的二分表和新的符號表。我們在重新編譯器之前仍然不必退出GDB。斷點相關操作設定斷點GDB設定點的後,該斷點的有效性會持續到刪除、禁用或退出GDB時。在某一行設定斷點:break line_number(行數)break filename:line_number 在原始碼檔案filename的line_number處設定斷點。在某個函數的入口(第一行可執行代碼)處設定斷點:break function(函數名)。這種方法相對以行數設定斷點有一個優點:如果修改了原始碼,使得函數不再在這一行處開始,那麼如果用函數名指定斷點,而不是用行號指定,則斷點仍然有效。注意:break function會在所有具有相同名稱的函數上設定斷點,注意函數重載的情況。break filename: function 在原始碼檔案filename的函數function入口處處設定斷點。當GDB使用多個斷點中斷一行原始碼時,它只會中斷一次。GDB實際設定斷點的位置可能和我們請求將斷點放置的位置不同。比如下列代碼:

int main(void){    int i;    i = 3;   return 0;}

如果我們嘗試在函數main入口處設定斷點,斷點實際會被設定在第4行。因為GDB會認為第三行的機器碼對我們的調試目的來說沒有用處。條件斷點將正常斷點轉變為條件斷點:condition break_p_num(斷點編號) cond(條件)在有效C條件陳述式中幾乎可以用任何錶達式。也可以用自己的函數或者庫函數,只要他們被連結到程式中。如:condition 1 num_y == 1隻有當滿足條件num_y == 1時,GDB才會在斷點1處暫停程式的執行。如果以後要刪除條件,但是保持斷點,只需鍵入:cond break_p_num(斷點編號)用break if可以將break和condition命令組合成一個步驟:break line_num(行號) if cond(條件)例子:(gdb) nreak 30 if num_y == 1注意,條件陳述式可以用括弧()括起來,也可以不用。臨時斷點:tbreak與break類似,但是這一命令設定的斷點在首次到達該指定行後就不再有效。刪除斷點基於標識符刪除斷點:deletedelete break_point_num(斷點編號),可以在後面指定多個斷點編號連續刪除幾個斷點delete:刪除所有斷點另一種刪除斷點方式:clear依據位置刪除斷點,工作方式和對應的break命令相似:clear functionclear filename:funtionclear line_numberclear filename:line_numberclear:清除GDB將執行的下一個指令處的斷點禁用與啟用斷點禁用斷點:disable breakpoint-list(是用空格分隔開的多個斷點標識符)禁用所有現存斷點:disable啟用斷點:enable breakpoint-list在下次引起GDB暫停執行後禁用:enable once breakpoint-list查看所有斷點資訊:info break或者是info breakpoints或者簡寫為i b斷點命令列表讓GDB在每次到達某個斷點時自動執行一組命令,從而自動完成某一任務。使用commands命令設定命令列表:commands breakpoint_number...commands...end例如以下代碼:

我打算查看傳遞給fibonacci函數的值以及次序,但是不想在程式中插入printf語句並重新編譯代碼,可以這樣做:在該函數入口處設定一個斷點,然後設定命令列表:

printf命令和C中printf函數類似,只是括弧是可選的。運行結果:

如果嫌GDB輸出太冗長,可以使用silent命令,只需將其添加到設定的命令列表最開始處即可。


恢複執行三種方法(1)逐步執行:step(s)、next(n),僅執行到代碼的下一行後再次暫停。注意二者區別:在函數調用時step會進入函數,next導致下一次暫停出現在調用函數之後。next被稱為單步越過(stepping over)函數,而step被稱為單步進入(stepping into)函數。next和step都可以採用一個可選的數值參數,來表示要使用next或step執行的額外行數。(2)無條件恢複程式的執行:continue(c)直到遇到另一個斷點或者程式結束。continue可以接受一個可選的數值參數n,要求GDB忽略下面n個斷點。(3)用finish(fin)或until(u)命令恢複。finish命令指示GDB恢複執行,直到恰好在當前幀完成之後為止。until命令通常用來在不進一步在迴圈中暫停(除了迴圈中的中間斷點)的情況下完成正在執行的迴圈。until會執行迴圈的其餘部分(如果遇到斷點,還是會暫停),讓GDB在迴圈後面的第一行代碼處暫停。until命令也可以接受原始碼中的位置作為參數,其用法與break命令同。比如下列代碼清單swapflaw.c:
#include <stdio.h>void swap(int *a,int *b){        int c = *a;        *a = *b;        *b = c;}int main(void){        int i = 3;        int j = 5;        printf("i:%d,j:%d\n",i,j);        swap(&i,&j);        printf("i:%d,j:%d\n",i,j);        return 0;}

如果GDB觸發了main函數入口處的一個斷點,那麼可以使用下面這些命令方便地使程式一直執行到swap()的入口:until 13until swapuntil swapflaw.c:13until swapflaw.c:swap監視點監視點是一種特殊類型的斷點,區別在於監視點沒有“住在”某一行原始碼中,而是指示GDB每當某個運算式改變了值就暫停執行。設定監視點:watch z(變數名)也可以是複雜的運算式注意只能監視存在且在範圍內的變數。一旦變數不再存在調用棧的任何幀中,GDB會自動刪除監視點。GDB實際上是在變數的記憶體位置改變值時中斷。檔案清單(gdb) list line1,line2查看原始碼list lineNum 在lineNum的前後原始碼顯示出來list + 列出當前行的後面程式碼list - 列出當前行的前面程式碼list functionset listsize count設定顯示代碼的行數show listsize顯示列印代碼的行數list first,last顯示從first到last的原始碼行GDB開機檔案的使用有時候我們在完成調試前可能需要退出GDB,比如需要離開比較長的一段時間而且不能保持登入在電腦中。為了不丟失某些資訊,可以將斷點和設定的其他命令放在一個GDB開機檔案中,然後每次啟動GDB時會自動載入它們。GDB開機檔案預設名為.gdbinit。可以將一個檔案放在主目錄中用於一般用途,另一個檔案放在特定項目專用的目錄中。例如,可以將設定斷點的命令放在後一個目錄的開機檔案中,在主目錄的.gdbinit檔案中儲存開發的一些通用的宏。最好不要將編程項目放在主目錄中,因為不能將項目特有的資訊放在.gdbinit中。在調用GDB時可以指定開機檔案,如:$gdb -command=z x表示要在可執行檔x上運行GDB,首先要從檔案z中讀取命令。

相關文章

聯繫我們

該頁面正文內容均來源於網絡整理,並不代表阿里雲官方的觀點,該頁面所提到的產品和服務也與阿里云無關,如果該頁面內容對您造成了困擾,歡迎寫郵件給我們,收到郵件我們將在5個工作日內處理。

如果您發現本社區中有涉嫌抄襲的內容,歡迎發送郵件至: info-contact@alibabacloud.com 進行舉報並提供相關證據,工作人員會在 5 個工作天內聯絡您,一經查實,本站將立刻刪除涉嫌侵權內容。

A Free Trial That Lets You Build Big!

Start building with 50+ products and up to 12 months usage for Elastic Compute Service

  • Sales Support

    1 on 1 presale consultation

  • After-Sales Support

    24/7 Technical Support 6 Free Tickets per Quarter Faster Response

  • Alibaba Cloud offers highly flexible support services tailored to meet your exact needs.