linux 下c如何使用gdb調試

參考:https://www.cnblogs.com/kingos/p/4514756.html

總結:

  • 生成可執行文件
  1. gcc -g test.c -o test(-g選項告訴gcc在編譯程序時加入調試信息)。
  • 進入調試模式,調試test.c文件
  1. gdb test 
  2. gdb -q test
  • 查看源代碼
  1. list默認一次顯示10行,直接回車重複上次命令,顯示接下來的10行,show listsize可查看參數,set listsize<count>可更改。
  2. list 5,10 顯示5到10行
  3. list func 顯示func函數週圍代碼,顯示範圍和list參數有關
  4. list test.c:5,10 顯示源文件test.c中第5行到第10行的代碼,一般用於調試含多個源文件的程序
  5. search str,從當前行開始,向前查找含str的字符串
  6. reverse-search str,從當前行開始,向後查找含str的字符串
  • 清空屏幕
  1. shell clear
  • 設置斷點
  1. break 6,在第6行設置斷點,讓程序停在第6行之前
  2. break 7 if n == 6,如果n的值等於6,則程序運行到第七行停止
  • 查看斷點信息
  1. info breakpoints
  • 斷點失效
  1. disable 1,第一個斷點失效,可通過info breakpoints來查看斷點的Enb值是否爲n來確定斷點是否失效
  • 斷點恢復
  1. enable 1
  • 刪除斷點
  1. clear 6,此處的6爲斷點所在行號
  2. delete 1,此處的1爲斷點編號,也可同時刪除多個,編號之間用空格隔開
  3. detele, 全部刪除
  • 開始調試
  1. run,開始執行程序
  • 繼續運行
  1. continue,讓程序繼續運行,直到下個斷點或者結束
  2. next,繼續執行下一條語句
  3. step,跟蹤進入函數內部
  • 打印
  1. print 變量或者表達式,打印出變量或者表達式的值
  • 退出調試
  1. quit
  • 結束當前程序的調試
  1. kill
  • 單步執行一條機器指令
  1. nexti
  2. stepi

原文

gdb是linux下非常好用的一個調試工具,雖然它是命令行模式的調試工具,但是它的功能強大到你無法想象,這裏簡單介紹下gdb下常用的命令。

首先編譯生成可執行文件(這裏的test.c是一個簡單的求前n項和的程序)。

gcc -g test.c -o test(-g選項告訴gcc在編譯程序時加入調試信息)。
接下來可以這樣。

gdb test

然後你就會看到出現好多信息在屏幕上,大致說的是gdb的一些版本信息說明之類的,但是它對你調試程序沒用呀,所以,你可以加上-q選項,不輸出它們。

gdb -q test

wang@king:~$ gdb -q test
Reading symbols from test...done.
(gdb) 

 

有沒有覺得這個世界一下子清淨了許多。

也可以先進入gdb模式,然後再加載文件。

wang@king:~$ gdb -q
(gdb) file test
Reading symbols from test...done.
(gdb) 

好了,現在開始調試了,但是我還想看看我的代碼怎麼辦,gdb提供了一條命令,可以讓你的程序顯示出來。

複製代碼

(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) 
發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章