作者:良知猶存
轉載授權以及圍觀:歡迎添加微信號:Conscience_Remains
總述
在window下我們習慣了IDE的各種調試按鈕,說實話確實挺方便的,但到了Linux下,沒有那麼多的IDE支持我們調試,但是Linux有也有強大的命令行C/C++的調試工具——GDB,GNU提供的開源調試工具。
剛開始不習慣,使用多了我們就會喜歡上他,程序調試的單步執行,跳入函數,跳出函數,設置斷點,設置觀察點,查看變量。GDB都有,此外gdb還可以生成程序非法執行後core dump文件,這個文件有快照功能,在程序崩潰的時候保存了程序的堆棧等信息,我們執行core文件就可以方便的找程序崩潰的原因了。
一、編譯可以調試的代碼
在linux下對於單個c/c++文件編譯通常就是加-o 進行編譯成可執行文件,但是我們如果需要要調試,則需要加一個 -g 用來向編譯器進行表明該程序需要編譯成可以gdb調試的代碼,加上編譯信息,生成的執行文件就會變大,如圖所示。所以我們只在調試的時候進行 -g 編譯。Java調試的時候也是類似後續也說一哈java的Linux。
Makefile的文件中我們也是如上,只不過是在Makefile文件中 -o 編譯的時候添加 -g
二、調試過程
調用gdb調試,先查看電腦環境裏面是否有gdb調試器,一般我們安裝了gcc編譯器,就默認同時安裝了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 | 打印 變量信息 | |
q | quit | 退出GDB |
delete | delete | 刪除斷點 |
disp | display | 跟蹤查看某個變量,每次停下來都顯示它的值 |
st | start | 開始執行程序,在main函數的第一條語句前面停下來 |
watch | watch | 監視變量值的變化 |
file | file | 裝入需要調試的程序 |
bt | backtrace | 查看函數調用信息(堆棧) |
f | frame | 查看棧幀 f n 切換到編號爲n的棧 |
undisp (數字) | undisplay | 取消顯示 |
help | 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調試一些方法,裏面代碼是實踐過的,如果大家有什麼更好的思路,歡迎分享交流哈。
更多分享,掃碼關注我