C編譯: 使用gdb除錯

ii_chengzi發表於2019-11-07

gdb是 的簡稱。它是一款UNIX平臺的偵錯程式(debugger),可用於為C, C++, Objective-C, Java, Fortran等程式debug。

在gdb中,你可以透過設定 斷點(break point)來控制程式執行的進度,並檢視斷點時的變數和函式呼叫狀況,從而發現可能的問題。在許多IDE中,gdb擁有圖形化介面。

這裡主要介紹gdb的命令列使用,並以C程式為例。測試使用的計算機是Mac OS系統。

 

啟動gdb

下面的有兩個C檔案。(並沒有bug。我們使用gdb來檢視程式執行的細節)

程式的一個為 test.c,其中有主程式 main()mean.c程式中定義了 mean()函式,並在main()中呼叫。

test.c

#define ARRAYSIZE 4float mean(float, float);int main()
{    int i;    float a=4.5;    float b=5.5;    float rlt=0.0;    float array_a[ARRAYSIZE]={1.0, 2.0, 3.0, 4.0};    float array_b[ARRAYSIZE]={4.0, 3.0, 2.0, 1.0};    float array_rlt[ARRAYSIZE];    for(i = 0; i < ARRAYSIZE - 1; i++) {
        array_rlt[i] = mean(array_a[i], array_b[i]);
    }
    rlt = mean(a, b);    return 0;
}

 

mean.c

float mean(float a, float b)
{   return (a + b)/2.0;
}

 

使用gcc同時編譯上面兩個程式。為了使用gdb對進行除錯,必須使用 -g選項(在編譯時生成debugging資訊):

$gcc -g -o test test.c mean.c

生成main可執行檔案。

(如有必要,使用:

$chmod +x test

來增加使用者的執行許可權。)

 

進入gdb,準備除錯程式:

$gdb test

進入gdb的互動命令列。

 

顯示程式

我們可以直接顯示某一行的程式,比如檢視第9行程式:

(gdb) list 9

將顯示以第9行為中心,總共10行的程式。我們實際上編譯了兩個檔案,在沒有說明的情況下,預設為主程式檔案test.c:

4    
5    int main()
6    {
7        int i;
8        float a=4.5;
9        float b=5.5;
10        float rlt=0.0;
11    
12        float array_a[ARRAYSIZE]={1.0, 2.0, 3.0, 4.0};
13        float array_b[ARRAYSIZE]={4.0, 3.0, 2.0, 1.0};

 

如果要檢視mean.c中的內容,需要說明檔名:

(gdb) list mean.c:1

 

可以具體說明所要列出的程式行的範圍:

(gdb) list 5, 15

即顯示5-15行的程式。

 

顯示某個函式,比如:

(gdb) list mean

 

設定斷點

我們可以執行程式:

(gdb) run

程式正常結束。

 

執行程式並沒有什麼有趣的地方。gdb的主要功能在於能讓程式在中途暫停。

斷點(break point)是程式執行中的一個位置。在gdb中,當程式執行到該位置時,程式會暫停,我們可以檢視此時的程式狀況,比如變數的值。

 

我們可以在程式的某一行設定斷點,比如:

(gdb) break 16

將在test.c的第16行設定斷點。

 

你可以檢視自己設定的斷點:

(gdb) info break

每個斷點有一個識別序號。我們可以根據序號刪除某個斷點:

(gdb) delete 1

也可以刪除所有斷點:

(gdb) delete breakpoints

 

檢視斷點

設定斷點,並使用run執行程式,程式將執行到16行時暫停。gdb顯示:

Breakpoint 1, main () at test.c:16
16        for(i = 0; i < ARRAYSIZE - 1; i++) {

 

檢視斷點所在行:

(gdb) list

 

檢視斷點處的某個變數值:

(gdb) print a

(gdb) print array_a

 

檢視所有的區域性變數:

(gdb) info local

 

檢視此時的棧狀態 (反映了函式呼叫,見 Linux從程式到程式):

(gdb) info stack

 

可以更改變數的值。

(gdb) set var a=0.0

(gdb) set var array_a={0.0, 0.0, 1.0, 1.0}

當程式繼續執行時,將使用更改後的值。

 

如果我們將斷點設定在:

(gdb) break mean.c:2

此時棧中有兩個a,一個屬於main(),一個屬於mean()。我們可以用function::variable的方式區分:

(gdb) print mean::a

 

執行控制

讓程式從斷點開始,再多執行一行:

(gdb) step

也可以使用下面命令,從斷點恢復執行,直到下一個斷點:

(gdb) continue

使用 run重新開始執行。

 

幫助

你可以透過gdb的幫助學到更多:

(gdb) help

或者更具體的命令:

(gdb) help info

 

退出

使用下面命令退出gdb:

(gdb) quit

 

debug

下面是一個有bug的C程式,demo.c

#include <stdio.h>struct node {    int element;
};
typedef struct node *PNode;int main()
{    int i;
    PNode np=NULL;    for (i=0; i<10; i++) {
        printf("Hello World!");
    }
    printf("%d \n", np->element);
}

程式可以成功編譯,但執行將返回:

Segmentation fault

可以使用gdb來查詢問題。

 

Updata:

經 提醒: gdb命令可以只輸入首字母的縮寫,比如c代表continue,b代表break,q代表quit。

來自 “ ITPUB部落格 ” ,連結:http://blog.itpub.net/31543790/viewspace-2663158/,如需轉載,請註明出處,否則將追究法律責任。

相關文章