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 }
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值