GDB簡明教程

GDB簡明教程

目 錄
關於調試...................................................................................................................................
GDB簡介.................................................................................................................................
什麼是GDB.....................................................................................................................
如何獲得GDB.................................................................................................................
GDB的安裝.....................................................................................................................
準備工作...................................................................................................................................
GDB基本命令介紹.................................................................................................................
調試程序...........................................................................................................................
查看源文件信息...............................................................................................................
單步執行程序...................................................................................................................
設置斷點...........................................................................................................................
查看斷點...........................................................................................................................
Enable 和 Disable 一個斷點.........................................................................................
條件斷點...........................................................................................................................
刪除斷點...........................................................................................................................
查看變量...........................................................................................................................
查看內存堆棧...................................................................................................................
查看彙編代碼...................................................................................................................
查看堆棧信息...................................................................................................................
調試時調用函數...............................................................................................................
watchpoint.........................................................................................................................
在線幫助...........................................................................................................................
示例.........................................................................................................................................
附錄A:.................................................................................................................................
關於調試
在軟件開發過程中,調試是其中最重要的一環,很多時候,調試程序的時間比實際編寫代碼的時間要長的多。有的時候,我們本來認爲程序應該是按照這樣的邏輯運行的,程序的輸出是這樣,但是運行程序的時候卻不是按照我們預想的邏輯運行或者結果不是我們所預期的,怎麼辦呢?一行一行的讀程序,用腦子模擬計算機運行程序?所以,熟練掌握一種調試工具會給我們帶來巨大的幫助,從而大大的提高我們的生產率。
GDB簡介
什麼是GDB
在UNIX環境下,GDB是GNU開發工具包的一個重要組成部分,它是免費的命令行下的C/C++調試工具。
如何獲得GDB
GDB可以從GNU的網站上免費獲得:http://www.gnu.org/software/gdb/download/
GDB的安裝
安裝GDB需要root權限,請你的系統管理員按照說明安裝GDB。
準備工作
在我們真正開始GDB的旅程前,首先要作一些準備工作:
1. 編寫用於GDB調試的實驗程序(見附錄A)
2. 編譯實驗程序
用命令 g++ -g –o testing testing.cc
-g -- 用於產生帶調試信息的DEBUG版本(沒有-g則生成RELEASE版本)。
GDB基本命令介紹
調試程序
首先啓動GDB調試工具,命令:gdb testing
進入GDB的工作提示符下:
GNU gdb 5.0
Copyright 2000 Free Software Foundation, Inc.
GDB is free software, covered by the GNU General Public License, and you are
welcome to change it and/or distribute copies of it under certain conditions.
Type "show copying" to see the conditions.
There is absolutely no warranty for GDB. Type "show warranty" for details.
This GDB was configured as "sparc-sun-solaris2.8"...
(gdb)
查看源文件信息
相關命令:list <行號> ―― 用於顯示行號附近的源代碼
(gdb) list 0
1 #include <iostream>
2 #include <strings.h>
3 using namespace std;
4
5 void Fun(int k)
6 {
7 cout << " k = " << k << endl;
8 char a[]="abcde";
9 cout << " a = " << a << endl;
10 char* b = new char[k];
小技巧:再次回車將重複最近一次的命令
單步執行程序
相關命令: step ―― 用於單步執行代碼,遇到函數將進入函數內部
next ―― 執行下一條代碼,遇到函數不進入函數內部
finish ―― 一直運行到當前函數返回
until <行號> ―― 運行到某一行
設置斷點 概念:所謂斷點就是讓程序運行到某處,暫時停下來以便我們查看信息的地方。
相關命令: break <參數> ―― 用於在參數處設置斷點
tbreak <參數> ―― 用於設置臨時斷點,如果該斷點暫停了,那麼
該斷點就被刪除了
hbreak <參數>―― 用於設置硬件輔助斷點,和硬件相關
rbreak <參數> ―― 參數爲正則表達式,凡是具有和正則表達式相
匹配的函數名稱的函數處都設置爲斷點
通常,break是應用的最多的設置斷點的命令,break <參數>,參數可以是函數名稱,也可以是行數。
例如:
bream main - 在main 函數處設置斷點
break 7 ― 在程序的第五行處設置斷點
(gdb) break main
Breakpoint 1 at 0x10d70: file testing.cc, line 22.
(gdb) break 7
Breakpoint 2 at 0x10bfc: file testing.cc, line 7.
查看斷點
相關命令: info break - 用於查看斷點信息列表
例如:
(gdb) info break
Num Type Disp Enb Address What
1 breakpoint keep y 0x00010d70 in main at test.cc:22
2 breakpoint keep y 0x00010bfc in _Z3Funi at testing.cc:7
其中:
Num - 斷點號
Type - 斷點類型
Disp - 斷點的狀態,keep表示斷點暫停後繼續保持斷點;del表示斷點
暫停後自動刪除斷點;dis表示斷點暫停後Disable該斷點
Enb - 表示斷點是否是Enabled
Address - 斷點的內存地址
What - 斷點在源文件中的位置
Enable 和 Disable 一個斷點
相關命令: enable <Breakpoint Number>
disble <Breakpoint Numbe>
斷點號可以有多個,它們之間用空格分隔,
enable delete - 啓動斷點,一旦在斷點處暫停,就刪除該斷點;用
info break 查看時,該斷點的狀態(Disp)爲del
enable once - 啓動斷點,但是隻啓動一次,之後就關閉該斷點,
用info break查看時,該斷點的狀態(Disp)爲dis
條件斷點
相關命令: break <參數> if <條件> - 條件是任何合法的C/C++表達式或函數調
用,注意,GDB爲了設置斷點進行了的函數調用,但是實際程序並沒有調用該函數。
condition <Breakpoint Number> <條件> -用於對一個已知斷點設置條件
例如:
(gdb) list 12
7 cout << " k = " << k << endl;
8 char a[]="abcde";
9 cout << " a = " << a << endl;
10 char* b = new char[k];
11 bzero(b,k);
12 for(int i = 0; i < strlen(a); i++)
13 {
14 b[i] = a[strlen(a)-i];
15 }
16 cout << " b = " << b << endl;
(gdb) break 13 if i==5
Breakpoint 2 at 0x10c9c: file testing.cc, line 12.
(gdb) info break
Num Type Disp Enb Address What
2 breakpoint keep y 0x00010c9c in _Z3Funi at testing.cc:13
stop only if i == 5
刪除斷點
相關命令: delete break <Breakpoint Number> - 刪除指定斷點號的斷點
delete breakpoints - 刪除所有斷點
例如:
(gdb) info break
Num Type Disp Enb Address What
1 breakpoint keep y 0x00010cc8 in _Z3Funi at testing.cc:13
stop only if i == 5
(gdb) delete break 1
(gdb) info break
No breakpoints or watchpoints.
查看變量
相關命令: print /格式 <表達式> - 按照格式打印表達式的值
格式:
格式
含義
x
16進制
d
10進制
u
無符號整數
o
8進制
t
2進制
a
以16進制格式打印地址
c
字符格式
f
浮點格式
例如:
(gdb) list 13
8 char a[]="abcde";
9 cout << " a = " << a << endl;
10 char* b = new char[k];
11 bzero(b,k);
12 for(int i = 0; i < strlen(a); i++)
13 {
14 b[i] = a[strlen(a)-i];
15 }
16 cout << " b = " << b << endl;
17 delete [] b;
(gdb) break 13
Breakpoint 1 at 0x10cc8: file testing.cc, line 13.
(gdb) run
Starting program: /oracle/jian/test/testing
k = 100
a = abcde
Breakpoint 1, _Z3Funi (k=100) at testing.cc:14
14 b[i] = a[strlen(a)-i];
(gdb) print a
$1 = "abcde"
(gdb) print /c a
$2 = {97 'a', 98 'b', 99 'c', 100 'd', 101 'e', 0 '\000'}
查看內存堆棧
相關命令: x /格式 <地址> - 地址是任何合法的地址
格式由3部分組成NFU;
N - 查看的長度
F - 查看變量中的地址含義相同
U - 單位,
b - 字節
h - 雙字節
w - 四字節
g - 八字節
例如:
(gdb) x /a b
0x216c0: 0x0
(gdb) x /c b
0x216c0: 0 '\000'
(gdb) x /f a
0xffbef990: 1.2926117890983049e+161
查看彙編代碼
相關命令: disassemble - 顯示反彙編代碼
例如:
(gdb) disassemble
Dump of assembler code for function _Z3Funi:
0x10bf4 <_Z3Funi>: save %sp, -128, %sp
0x10bf8 <_Z3Funi+4>: st %i0, [ %fp + 0x44 ]
0x10bfc <_Z3Funi+8>: sethi %hi(0x21000), %o0
0x10c00 <_Z3Funi+12>: or %o0, 0x220, %o0 ! 0x21220
<_ZSt4cout>
0x10c04 <_Z3Funi+16>: sethi %hi(0x10c00), %o1
0x10c08 <_Z3Funi+20>: or %o1, 0x300, %o1 ! 0x10f00
<_lib_version+8>
0x10c0c<_Z3Funi+24>: call 0x20fc0
<_ZStlsISt11char_traitsIcEERSt13
basic_ostreamIcT_ES5_PKc>
0x10c10 <_Z3Funi+28>: nop
0x10c14 <_Z3Funi+32>: ld [ %fp + 0x44 ], %o1
0x10c18 <_Z3Funi+36>: call 0x20fcc <_ZNSolsEi>
0x10c1c <_Z3Funi+40>: nop
0x10c20 <_Z3Funi+44>: sethi %hi(0x20c00), %o1
---Type <return> to continue, or q <return> to quit---
查看堆棧信息
相關命令: bt - 查看當前堆棧frame情況
frame <Frame Number> - 顯示堆棧執行的語句的信息
info frame - 顯示當前frame的堆棧詳細信息
up - 查看上一個Frame Number的堆棧具體信息
down- 查看下一個Frame Number的堆棧具體信息
例如:
(gdb) bt
#0 _Z3Funi (k=100) at testing.cc:14
#1 0x10d7c in main () at testing.cc:22
(gdb) frame 0
#0 _Z3Funi (k=100) at testing.cc:14
14 b[i] = a[strlen(a)-i];
(gdb) info frame
Stack level 0, frame at 0xffbef9a8:
pc = 0x10cc8 in _Z3Funi (testing.cc:14); saved pc 0x10d7c
called by frame at 0xffbefa18
source language c++.
Arglist at 0xffbef9a8, args: k=100
Locals at 0xffbef9a8,
調試時調用函數
相關命令:call <函數> - 調用目標函數並且打印返回值
例如:
(gdb) call printf("hello\n") //調用printf函數
hello //printf函數的運行
$11 = 6
(gdb) call fflush() //調用並打印printf函數的返回值
$12 = 0
watchpoint
相關命令: watch <變量> - 查看變量的內容,其實watchpoint就是斷點
例如:
(gdb) break 13
Breakpoint 1 at 0x10cc8: file testing.cc, line 13.
(gdb) run
Starting program: /oracle/jian/test/testing
k = 100
a = abcde
Breakpoint 1, _Z3Funi (k=100) at testing.cc:14
14 b[i] = a[strlen(a)-i];
(gdb) watch b[i]
Hardware watchpoint 2: b[i]
(gdb) next
12 for(int i = 0; i < strlen(a); i++)
(gdb)
Breakpoint 1, _Z3Funi (k=100) at testing.cc:14
14 b[i] = a[strlen(a)-i];
(gdb)
Hardware watchpoint 2: b[i]
Old value = 0 '\000'
New value = 101 'e'
_Z3Funi (k=100) at testing.cc:12
12 for(int i = 0; i < strlen(a); i++)
在線幫助
相關命令: help
示例
使用GDB調試附錄A中的程序:
我們期望的程序運行結果:
k = 100
a = abcde
b = edcba
實際的運行結果:
k = 100
a = abcde
b = 問題出在哪兒?
我們的程序沒有按照我們所預期的輸出,問題出在b的輸出上。那麼讓我們用GDB來調試看看,問題究竟出在什麼地方。
1. 分析:
該程序的問題在於b的輸出,本來我們期待的輸出結果是b爲a的反相輸出,可現在b什麼都沒有輸出,問題最有可能就是在給b賦值時出現了問題。
2. 用GDB進行調試
/oracle/jian/test>gdb testing
GNU gdb 5.0
Copyright 2000 Free Software Foundation, Inc.
GDB is free software, covered by the GNU General Public License, and you are
welcome to change it and/or distribute copies of it under certain conditions.
Type "show copying" to see the conditions.
There is absolutely no warranty for GDB. Type "show warranty" for details.
This GDB was configured as "sparc-sun-solaris2.8"...
(gdb) list 0
1 #include <iostream>
2 #include <strings.h>
3 using namespace std;
4
5 void Fun(int k)
6 {
7 cout << " k = " << k << endl;
8 char a[]="abcde";
9 cout << " a = " << a << endl;
10 char* b = new char[k];
(gdb)
11 bzero(b,k);
12 for(int i = 0; i < strlen(a); i++)
13 {
14 b[i] = a[strlen(a)-i];
15 }
16 cout << " b = " << b << endl;
17 delete [] b;
18 }
19
20 int main()
(gdb) break 16
Breakpoint 1 at 0x10d10: file testing.cc, line 16.
(gdb) run
Starting program: /oracle/jian/test/testing
k = 100
a = abcde
Breakpoint 1, _Z3Funi (k=100) at testing.cc:16
16 cout << " b = " << b << endl;
(gdb) print /c *b (查看b[0]的值)
$1 = 0 '\000'
(gdb) print /c *(b+1) (查看b[1]的值)
$2 = 101 'e'
(gdb) print /c *(b+2) (查看b[2]的值)
$3 = 100 'd'
(gdb) finish
Run till exit from #0 _Z3Funi (k=100) at testing.cc:16
b =
main () at testing.cc:23
23 return 0;
(gdb)
3. 分析現象,提出解決方法
問題在於打印語句是以’\0’作爲結束的,現在b[0]的值恰恰是’\0’。
那麼這個’\0’又是從何來的呢?顯然是a的最後一個結束標記,所以,將a反相賦值給b時,應該去掉最後的那個’\0’。
4. 修改程序從新編譯,再測試,所得到的結果就是我們所希望的了。
將第14行的b[i] = a[strlen(a)-i]; 更改爲b[i] = a[strlen(a)-i-1]; 即可。
附錄A:
<< testing.cc >>
1 #include <iostream>
2 #include <strings.h>
3 using namespace std;
4
5 void Fun(int k)
6 {
7 cout << " k = " << k << endl;
8 char a[]="abcde";
9 cout << " a = " << a << endl;
10 char* b = new char[k];
11 bzero(b,k);
12 for(int i = 0; i < strlen(a); i++)
13 {
14 b[i] = a[strlen(a)-i];
15 }
16 cout << " b = " << b << endl;
17 delete [] b;
18 }
19
20 int main()
21 {
22 Fun(100);
23 return 0;
24
25 }
發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章