天天看點

一文入門Linux下gdb調試(一)

作者:良知猶存

轉載授權以及圍觀:歡迎添加微信号:Conscience_Remains

總述

    在window下我們習慣了IDE的各種調試按鈕,說實話确實挺友善的,但到了Linux下,沒有那麼多的IDE支援我們調試,但是Linux有也有強大的指令行C/C++的調試工具——GDB,GNU提供的開源調試工具。

    剛開始不習慣,使用多了我們就會喜歡上他,程式調試的單步執行,跳入函數,跳出函數,設定斷點,設定觀察點,檢視變量。GDB都有,此外gdb還可以生成程式非法執行後core dump檔案,這個檔案有快照功能,在程式崩潰的時候儲存了程式的堆棧等資訊,我們執行core檔案就可以友善的找程式崩潰的原因了。

一、編譯可以調試的代碼

一文入門Linux下gdb調試(一)
    在linux下對于單個c/c++檔案編譯通常就是加-o 進行編譯成可執行檔案,但是我們如果需要要調試,則需要加一個 -g 用來向編譯器進行表明該程式需要編譯成可以gdb調試的代碼,加上編譯資訊,生成的執行檔案就會變大,如圖所示。是以我們隻在調試的時候進行 -g 編譯。Java調試的時候也是類似後續也說一哈java的Linux。
一文入門Linux下gdb調試(一)
Makefile的檔案中我們也是如上,隻不過是在Makefile檔案中 -o 編譯的時候添加 -g
一文入門Linux下gdb調試(一)
二、調試過程
一文入門Linux下gdb調試(一)
調用gdb調試,先檢視電腦環境裡面是否有gdb調試器,一般我們安裝了gcc編譯器,就預設同時安裝了gdb調試器
一文入門Linux下gdb調試(一)
沒有的話要安裝gdb調試器,使用apt-get 就可以快速安裝

apt-get update              ​              apt-get install  gdb           

gdb 調用執行檔案 

gdb ./big_endian /*執行檔案*/           

最基本的GDB指令

指令 全稱 解釋
l list 檢視源碼
b break 設定斷點
r run 運作程式,在斷點處停止
n next 單條語句執行
c continue 繼續運作程式,下一個斷點處停止 
p print 列印 變量資訊
q quit 退出GDB
delete  删除斷點
disp  display   跟蹤檢視某個變量,每次停下來都顯示它的值  
st    start    開始執行程式,在main函數的第一條語句前面停下來
watch  監視變量值的變化
file   裝入需要調試的程式
bt    backtrace  檢視函數調用資訊(堆棧)  
 f frame      檢視棧幀 f n 切換到編号為n的棧
undisp (數字) undisplay  取消顯示
help 幫助指令
set (args 10 20 30 40 50 ) 可指定運作參數
s step 執行到函數内部

示例執行:

/*剛開始有很多列印的資訊*/
book@lyn:~/Documents/linux/test/wds/wds_c++/c++_test1/c11th$ gdb person1
GNU gdb (Ubuntu 7.11.1-0ubuntu1~16.5) 7.11.1
Copyright (C) 2016 Free Software Foundation, Inc.
License GPLv3+: GNU GPL version 3 or later <http://gnu.org/licenses/gpl.html>
This is free software: you are free to change and redistribute it.
There is NO WARRANTY, to the extent permitted by law.  Type "show copying"
and "show warranty" for details.
This GDB was configured as "x86_64-linux-gnu".
Type "show configuration" for configuration details.
For bug reporting instructions, please see:
<http://www.gnu.org/software/gdb/bugs/>.
Find the GDB manual and other documentation resources online at:
<http://www.gnu.org/software/gdb/documentation/>.
For help, type "help".
Type "apropos word" to search for commands related to "word"...
Reading symbols from person1...done.
(gdb) l 10  /*list 10  顯示10行代碼 友善下一步打斷點調試*/
5       using namespace std;
6
7       class Person {
8       private:
9               static int cnt;
10              char *name;
11              int age;
12
13      public:
14
(gdb)   /*不輸入 直接 Enter 鍵 重複上一步驟*/
15              static int getCount(void); 
16
17              Person() {//cout <<"Pserson()"<<endl;
18                      name = NULL;
19                      cnt++;
20              }
21              Person(char *name) 
22              {
23                      //cout <<"Pserson(char *)"<<endl;
24                      this->name = new char[strlen(name) + 1];
(gdb) 
25                      strcpy(this->name, name);
26                      cnt++;
27              }
28
29              Person(char *name, int age) 
30              {
31                      cout <<"Pserson(char*, int), name = "<<name<<", age= "<<age<<endl;
32                      this->age = age;
33
34                      this->name = new char[strlen(name) + 1];
(gdb) /*......*/
......
95
96      int main(int argc, char **argv)
97      {
98              Student p;
99              p.setName("zhangsan");
100             p.setAge(16);
101             p.printInfo();
102
103             return 0;
104     }
(gdb) b 99 /*在顯示的 第 99行代碼處 打斷點*/
Breakpoint 1 at 0x400b5d: file person.cpp, line 99.
(gdb) i b /*顯示 設定的斷點*/
Num     Type           Disp Enb Address            What
1       breakpoint     keep y   0x0000000000400b5d in main(int, char**) at person.cpp:99
(gdb) r  /*開始全速執行代碼 直到第一個斷點處*/
Starting program: /home/book/Documents/linux/test/wds/wds_c++/c++
Breakpoint 1, main (argc=1, argv=0x7fffffffe3d8) at person.cpp:99
99              p.setName("zhangsan");
(gdb) p p  /*列印 p 變量資訊*/
$1 = {<Person> = {static cnt = 1, name = 0x0, age = 0}, <No data fields>}
(gdb) n  /*執行下一步*/
100             p.setAge(16);
(gdb) q  /*退出 gdb 調試*/
A debugging session is active.
​
        Inferior 1 [process 3410] will be killed.
​
Quit anyway? (y or n) y


(gdb) i disp  /*顯示所有的disp變量*/
Auto-display expressions now in effect:
Num Enb Expression
1:   y  ap
2:   y  * ap
3:   y  *ap
4:   y  val
(gdb) undisplay 1 /*取消顯示第一個變量*/
(gdb) undisplay 2
(gdb) undisp 3
(gdb) i disp /*檢視确認*/
Auto-display expressions now in effect:
Num Enb Expression
4:   y  val


(gdb) s
hanoi (n=3, x=120 'x', y=121 'y', z=122 'z') at Hanoi.c:21
21              if(n==1)                                                        //欲移動n個圓盤,需先移動其上的n-1個圓盤 
(gdb) n
25                      hanoi(n-1, x, z, y);                    //将x上編号為1至n-1的圓盤移到y,z作輔助塔 
      

  

 這就是我分享的gdb調試一些方法,裡面代碼是實踐過的,如果大家有什麼更好的思路,歡迎分享交流哈。

一文入門Linux下gdb調試(一)

更多分享,掃碼關注我