編寫test2.c
gcc test2.c -g -o test2
gdb test2
進入gdb調試
run指令
run指令格式
run <arg1...argn>
其中run可以簡寫成r,gdb中大部分指令可以簡寫。
在gdb中執行
run lvyahui blog
可以看到輸出
再次運作run可以不需要再傳遞參數,它會使用最後一次調用run指令傳遞的參數
可以看到預設參數
可以再次執行帶參數的run或者使用set agrs 修改預設參數
斷點
設定斷點
break <line-number>
可以在vim編輯器中檢視行号或者通過list/l指令檢視行号
編輯代碼檔案test1.c
編譯好test1
gcc test1.c -g -o test1
gdb test1
進入gdb環境
先檢視代碼,然後設定一個斷點,再run執行,讓後continue繼續執行
在方法前添加斷點
break可以直接在方法前添加短點
break fun_name
在此調試執行
删除斷點
下面看怎麼删除之前設定的短點
delete breakpoint <point-number> #删除指定斷點
#或者
delete breakpoints #删除所有斷點
其中 delete可以簡寫成d
另外clear指令也可以用來清除斷點
按表達式設定斷點
break <line number> if expression
按照上面的方法步驟設定斷點,發現失敗了,提示No symbol var in current context
起初我以為是這樣的設定需要在運作中設定,于是在13行設定斷點,運作,當停在13行時,再在第15行設定一個條件斷點,但
最後發現問題依舊。顯然問題不在這裡,後來上網查了下,在編譯時加上一個-gstabs+選項
gcc -g -gstabs+ -c test1.c
gcc test1.o -o test1
再次進入gdb 調試
發現就可以設定這個條件斷點了
可以使用readelf看兩次不同方法編譯生成的.o檔案的符号表有所不同。
run執行下看看
但是執行發現斷點沒有起作用
雖然不知道為什麼,但顯然之前是因為編譯器做了編譯優化,但我明明沒有加任何-OX選項啊。後來把i==50換成i>=50,發現可以停下來了。
真是郁悶,i怎麼會是這個值呢?
如果是多檔案程式,break還可以指定檔案添加斷點,格式如下
break <filename:line-number>
break <filename:fun-name>
#例如
break test1.c:15
break test1.c:main
禁止和啟用斷點
格式
disable/enable breakpoint num
觀察點
觀察點也可以起到斷點的作用
編輯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 指令需要在運作程式後使用看,是以我們要先加一個斷點讓程式停下來
将斷點删除,繼續執行
檢視運作資料
在運作時常常使用print指令來檢視資料,再次之前,需要先知道如何單步執行,進入函數,運作到下一個斷點
- next--執行一行源代碼但不進入函數内部。
- step--執行一行源代碼而且進入函數内部。
- continue -- 執行到下一暫停點或程式結束。
再次調試test1程式
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;
}
自動顯示變量
display/fmt expr
控制格式的字元更printf的非常相似,在此不做贅述
以上是個人總結的gdb的一些基礎内容,更多内容會在後續部落格中提及