天天看點

gdb調試程式

編寫test2.c

編譯成可執行檔案

gcc test2.c -g -o test2      
gdb test2      

進入gdb調試

run指令

run指令格式

run <arg1...argn>      

其中run可以簡寫成r,gdb中大部分指令可以簡寫。

在gdb中執行

run lvyahui blog      

可以看到輸出

gdb調試程式

再次運作run可以不需要再傳遞參數,它會使用最後一次調用run指令傳遞的參數

gdb調試程式

可以看到預設參數

gdb調試程式

可以再次執行帶參數的run或者使用set agrs 修改預設參數

gdb調試程式

斷點

設定斷點

break <line-number>      

可以在vim編輯器中檢視行号或者通過list/l指令檢視行号

gdb調試程式

編輯代碼檔案test1.c

gdb調試程式

編譯好test1

gcc test1.c -g -o test1      
gdb test1      

進入gdb環境

先檢視代碼,然後設定一個斷點,再run執行,讓後continue繼續執行

gdb調試程式

在方法前添加斷點

break可以直接在方法前添加短點

break fun_name      
gdb調試程式

在此調試執行

gdb調試程式

删除斷點

下面看怎麼删除之前設定的短點

delete breakpoint <point-number> #删除指定斷點
#或者
delete breakpoints  #删除所有斷點      

其中 delete可以簡寫成d

gdb調試程式

另外clear指令也可以用來清除斷點

按表達式設定斷點

break <line number> if expression      
gdb調試程式

按照上面的方法步驟設定斷點,發現失敗了,提示No symbol var in current context

起初我以為是這樣的設定需要在運作中設定,于是在13行設定斷點,運作,當停在13行時,再在第15行設定一個條件斷點,但

最後發現問題依舊。顯然問題不在這裡,後來上網查了下,在編譯時加上一個-gstabs+選項

gcc -g -gstabs+ -c test1.c
gcc test1.o -o test1      

再次進入gdb 調試

發現就可以設定這個條件斷點了

gdb調試程式

可以使用readelf看兩次不同方法編譯生成的.o檔案的符号表有所不同。

run執行下看看

但是執行發現斷點沒有起作用

gdb調試程式

雖然不知道為什麼,但顯然之前是因為編譯器做了編譯優化,但我明明沒有加任何-OX選項啊。後來把i==50換成i>=50,發現可以停下來了。

gdb調試程式

真是郁悶,i怎麼會是這個值呢?

如果是多檔案程式,break還可以指定檔案添加斷點,格式如下

break <filename:line-number>
break <filename:fun-name>
#例如
break test1.c:15
break test1.c:main      

禁止和啟用斷點

格式

disable/enable breakpoint num      
gdb調試程式

觀察點

觀察點也可以起到斷點的作用

編輯test3.c檔案

#include <stdio.h>

int sum(int a){
    int i,res = 0;
    for(i=0;i < a;i++){
        res += i;
    }
    return res;
}
int main(void){
    int a = 10;
    int asum = sum(a);
    printf("asum is %d \n",asum);
    return 0;
}      

編譯

gcc -g -gstabs+ -Wall test3.c -o test3      

watch 指令需要在運作程式後使用看,是以我們要先加一個斷點讓程式停下來

gdb調試程式

将斷點删除,繼續執行

gdb調試程式

檢視運作資料

在運作時常常使用print指令來檢視資料,再次之前,需要先知道如何單步執行,進入函數,運作到下一個斷點

  • next--執行一行源代碼但不進入函數内部。
  • step--執行一行源代碼而且進入函數内部。
  • continue -- 執行到下一暫停點或程式結束。

再次調試test1程式

gdb調試程式

print的格式

print <expression>
#或者
p <expression>      

其中expression可以是各種形式

表達式

p (i-6)*3+result      

函數調用

p func(5)      

數組

p *arr_name@arr_length      

編寫test4.c

#include <stdio.h>
#include <string.h>

int main(void){
    int arr[] = {1,2,3,4,5};
    int len = 4,i;
    int * arr2 = (int *) malloc(len * sizeof(int));
    for(i=0;i<len;i++){
        arr2[i]= i*2;
    }
    free(arr2);
    return 0;
}      
gdb調試程式

自動顯示變量

display/fmt expr      
gdb調試程式

控制格式的字元更printf的非常相似,在此不做贅述

以上是個人總結的gdb的一些基礎内容,更多内容會在後續部落格中提及

繼續閱讀