gdb是linux下很是好用的一個調試工具,雖然它是命令行模式的調試工具,可是它的功能強大到你沒法想象,這裏簡單介紹下gdb下經常使用的命令。linux
首先編譯生成可執行文件(這裏的test.c是一個簡單的求前n項和的程序)。shell
gcc -g test.c -o test(-g選項告訴gcc在編譯程序時加入調試信息)。
接下來能夠這樣。session
gdb test 函數
而後你就會看到出現好多信息在屏幕上,大體說的是gdb的一些版本信息說明之類的,可是它對你調試程序沒用呀,因此,你能夠加上-q選項,不輸出它們。工具
gdb -q testui
wang@king:~$ gdb -q test Reading symbols from test...done. (gdb)
有沒有以爲這個世界一會兒清淨了許多。spa
也能夠先進入gdb模式,而後再加載文件。命令行
wang@king:~$ gdb -q (gdb) file test Reading symbols from test...done. (gdb)
好了,如今開始調試了,可是我還想看看個人代碼怎麼辦,gdb提供了一條命令,可讓你的程序顯示出來。debug
(gdb) //list默認一次顯示10行 1 #include<stdio.h> 2 int func(int n) 3 { 4 int i; 5 int sum=0; 6 for(i=0;i<n;i++) 7 { 8 sum+=i; 9 } 10 return sum; (gdb) //直接輸入回車重複上次命令,顯示接下來的10行 11 } 12 int main() 13 { 14 int n; 15 printf("請輸入n的值"); 16 scanf("%d",&n); 17 printf("1+2+..+%d=%d",n,func(n)); 18 return 0; 19 } (gdb)
list默認參數能夠用show listsize來查看,若是感受10行太多或者太少,還能夠用set listsize <count>來更改。調試
list 還能夠加上其餘參數,好比:
list 5,10 顯示第5行到第10行的代碼;
list func 顯示func函數週圍的代碼,顯示範圍和list參數有關;
list test.c:5,10 顯示源文件test.c第5行到第10行的代碼,通常用於調試含多個源文件的程序。
gdb 還支持字符串查找,search str,從當前行開始,向前查找含str的字符串;
reverse-search str,從當前行開始,向後查找含str的字符串。
如今你的屏幕應該被佔滿了吧?想清空屏幕,但是還在gdb裏面呀,怎麼辦?其實,gdb也支持運行linux命令的,能夠在gdb的提示符中,輸入shell,而後在輸入你須要的命令就能夠了
(gdb) shell clear
這樣也能達到清屏的效果。
看了程序的代碼,感受第6行代碼可能有點問題,如今就須要我就須要設置一個斷點,讓程序停在第6行以前。
(gdb) break 6 Breakpoint 1 at 0x80484c8: file test.c, line 6. (gdb)
下面一行的 信息,1說明我設置的這個斷點是第一個斷點,斷點所在內存地址爲0x80484c8,它在文件test.c的第6行。
gdb還能夠以條件表達式設置斷點。
(gdb) break 7 if n==6 Breakpoint 2 at 0x80484d1: file test.c, line 7. (gdb)
這個斷點的含義是,若是n的值爲6,則程序運行到第7行中止。
固然,還能夠直接在某個函數處設置斷點;直接break 函數名就能夠了,
而後咱們想看下設置的斷點信息,可使用info breakpoints命令。
(gdb) info breakpoints Num Type Disp Enb Address What 1 breakpoint keep y 0x080484c8 in func at test.c:6 2 breakpoint keep y 0x080484d1 in func at test.c:7 stop only if n==6 4 breakpoint keep y 0x080484c1 in func at test.c:5 (gdb)
Num表示斷點的編號;Type表示斷點的斷點的類型,第二個斷點類型還加上了條件;Disp表示中斷點在執行一次以後是否失去做用,dis爲是,keep爲不是;Enb表示當前中斷點是否有效,y爲是,n爲否;Address表示中斷點所處的內存地址;What指出斷點所處的位置。
若是不須要程序在該斷點暫停時,有兩種方法,一種是使該斷點失效,一種是直接刪除該斷點。
(gdb) disable 1 (gdb) info breakpoints Num Type Disp Enb Address What 1 breakpoint keep n 0x080484c8 in func at test.c:6 2 breakpoint keep y 0x080484d1 in func at test.c:7 stop only if n==6 3 breakpoint keep y 0x080484c1 in func at test.c:5 (gdb)
能夠看到,第一個斷點的Enb變爲n了,表示該斷點已經無效了,若是須要恢復,可使用enable命令。這裏須要注意的是,disable後面的參數爲斷點的編號。而不是行號。
直接刪除該斷點,可使用clear命令和delete命令。
(gdb) clear 6 已刪除的斷點 1 (gdb)
clear命令後面的參數爲設置斷點的行號,clear後面參數還能夠加設置斷點的函數名。
delete命令後面的參數爲斷點的編號;能夠一次刪除多個斷點,斷點編號之間用空格隔開;若是delete後沒有參數,默認刪除因此斷點,會給出提示選擇是否操做。
(gdb) delete
刪除全部斷點嗎? (y or n)
斷點設置好了,如今就能夠調試了,
(gdb) run //開始執行程序 Starting program: /home/wang/test 請輸入n的值10 Breakpoint 1, func (n=10) at test.c:6 //設置的第一個斷點,程序在第6行暫停 6 for(i=0;i<n;i++) (gdb) continue //讓程序繼續運行,直到下個斷點或者結束 Continuing. Breakpoint 2, func (n=10) at test.c:8 //第二個斷點設置的是i==6時中止 8 sum+=i; (gdb) print i //用print命令打印出i的值 $1 = 6 (gdb) print sum $2 = 15 (gdb) next //繼續執行下一條語句,只執行一條。 6 for(i=0;i<n;i++) (gdb) next 8 sum+=i; (gdb) print i $3 = 7 (gdb) continue Continuing. 1+2+..+10=45[Inferior 1 (process 23636) exited normally] (gdb) quit //退出gdb調試
上面出現了不少命令,下面就來講說都是怎麼用的。
run,開始運行程序;
continue,程序暫停時繼續運行程序的命令;
print 變量名或表達式,打印該變量或者該表達式的值。whatis 變量名或者表達式,能夠顯示該變量或表達式的數據類型。
print 變量=值,這種形式還能夠給對應的變量賦值;相似的還有set variable 變量=值。做用和用print賦值相同。
next,繼續執行下一條語句;還有一條命令step,與之相似,不一樣的是,當下一條語句遇到函數調用的時候,next不會跟蹤進入函數,而是繼續執行下面的語句,而step命令則會跟蹤進入函數內部。
(gdb) run Starting program: /home/wang/test Breakpoint 1, main () at test.c:16 16 scanf("%d",&n); (gdb) next 請輸入n的值10 17 printf("1+2+..+%d=%d",n,func(n)); (gdb) next //next命令直接執行下一行,沒有進入func函數 18 return 0; (gdb)
(gdb) run Starting program: /home/wang/test Breakpoint 1, main () at test.c:16 16 scanf("%d",&n); (gdb) n 請輸入n的值10 17 printf("1+2+..+%d=%d",n,func(n)); (gdb) step //step命令跟蹤進入了func函數 func (n=10) at test.c:5 5 int sum=0; (gdb)
還有nexti和stepi命令,這兩個是單步執行一條機器指令,好比(i=0;i<n;i++)這條語句須要輸入多個nexti才能執行完;兩個的區別和上面相同。
quit,退出gdb調試,若是調試中想要退出,能夠直接輸入該命令,會出現提示選擇是否退出。kill命令,結束當前程序的調試,(不會退出gdb)。
(gdb) quit A debugging session is active. Inferior 1 [process 32229] will be killed. Quit anyway? (y or n)