介绍:
GDB是GNU开源组织发布的一个强大的UNIX下的程序调试工具。或许,各位比较喜欢那种图形界面方式的,像VC、BCB等IDE的调试,但如果你是在UNIX,Linux平台下做软件,你会发现GDB这个调试工具有比VC、BCB的图形化调试器更强大的功能。所谓“寸有所长,尺有所短”就是这个道理。
GDB的命令很多,这里不一定面面俱到。先介绍GDB中的一个非常有用的功能:补齐功能。它就如同Ubuntu下SHELL中的命令补齐一样。当你 输入一个命令的前几个字符,然后输入TAB键,如果没有其它命令的前几个字符与此相同,SHELL将补齐此命令。如果有其它命令的前几个字符与此相同,你 会听到一声警告声,再输入TAB键,SHELL将所有前几个字符与此相同的命令全部列出。而GDB中的补齐功能不仅能补齐GDB命令,而且能补齐参数。
而且大部分GDB内的命令都可以仅输入前几个字符,只要不与其它
指令冲突。如quit可以简写为q,因为以q打头的命令只有quit。List可以简写为l,等等。
1.启动GDB
启动GDB命令是在SHELL下输入的,你可以输入GDB来启动GDB程序。如果你已经编译好一个程序,我们假设文件名为hello (注意想用GDB调试它,必须在编译时带上g参数,例如
$ g++ -g -o hello hello.c
得到hello文件),然后输入
$ gdb hello
来启动GDB并载入程序。如果已经启动了GDB,使用file命令。如
gdb> file hello
也可在GDB中再载入程序。注意:路径名要正确。
2.退出GDB === q
在GDB的命令方式下,输入quit,就可以退出GDB。也可以输入'C-d'来退出GDB。
3.运行程序=== r
在GDB中已将要调试的程序载入后,可以用run命令来执行。如果程序需要参数,在run
指令后接着输入参数,就象在SHELL下执行一个需要参数的命令一样。
表1. gdb中最常用的命令 命令
说明
例子
help 显示命令类别 help -显示命令类别
help breakpoints -显示属于breakpoints类别的命令
help break -显示break命令的解释 run 启动所调试的程序 ? kill 终止正在调试的程序的执行 通常这会在要执行的代码行已经超过了您想要调试的代码时使用。执行kill会重置断点,并从头再次运行这个程序 cont 所调试的程序运行到一个断点、异常或单步之后,继续执行 ? info break 显示当前的断点或观察点 ? break 在指定的行或函数处设置断点 break 93 if i=8 -当变量i等于8时,在第93行停止程序执行 Step 单步执行程序,直到它到达一个不同的源代码行。您可以使用s来代表step命令 ? Next 与step命令类似,只是它不会“单步跟踪到”子例程中 ? print 打印一个变量或表达式的值 print pointer -打印变量指针的内容
print *pointer -打印指针所指向的数据结构的内容 delete 删除某些断点或自动显示表达式 delete 1 -删除断点1。断点可以通过info break来显示 watch 为一个表达式设置一个观察点。当表达式的值发生变化时,这个观察点就会暂停程序的执行 ? where 打印所有堆栈帧的栈信息 where -不使用参数,输出当前线程的堆栈信息
where all -输出当前线程组中所有线程的堆栈信息
where threadindex -输出指定线程的堆栈信息 attach 开始查看一个已经运行的进程 attach <process_id> -附加到进程process_id上。process_id可以使用ps命令找到 info thread 显示当前正在运行的线程 ? thread apply threadno command 对一个线程运行gdb命令 thread apply 3 where -对线程3运行where命令 Thread threadno 选择一个线程作为当前线程 ? 4.查看程序信息=== info
info
指令用来查看程序的信息,用help info查看帮助的话,会显示info
指令的参数非常多,但info
指令最多的是用它来查看断点信息。
4.1查看断点信息
info br
br是断点break的缩写,记得GDB的补齐功能吧。用这条
指令,你可以得到你所设置的所有断点的详细信息。包括断点号,类型,状态,内存地址,断点在源程序中的位置等。
4.2查看当前源程序
info source
4.3查看堆栈信息
info stack
用这条
指令你可以看清楚程序的调用层次关系。
4.4查看当前的参数
info args
5.列出源一段源代码=== l
5.1列出某个函数
list FUNCTION
5.2以当前源文件的某行为中间显示一段源程序
list LINENUM
5.3接着前一次继续显示
list
5.4显示前一次之前的源程序
list -
5.5显示另一个文件的一段程序
list FILENAME:FUNCTION或list FILENAME:LINENUM
6.设置断点=== break
现在我们将要介绍的也许是最常用和最重要的命令:设置断点。无论何时,只要程序已被载入,并且当前没有正在运行,就能设置,修改,删除断点。设置断点的命令是break。有许多种设置断点的方法。如下:
6.1在函数入口设置断点
break FUNCTION
6.2在当前源文件的某一行上设置断点
break LINENUM
6.3在另一个源文件的某一行上设置断点
break FILENAME:LINENUM
6.4在某个地址上设置断点,当你调试的程序没有源程序是,这很有用
break *ADDRESS
除此之外,设置一个断点,让它只有在某些特定的条件成立时程序才会停下,我们可以称其为条件断点。这个功能很有用,尤其是当你要在一个程序会很多次 执行到的地方设置断点时。如果没有这个功能,你必须有极大的耐心,加上大量的时间,一次一次让程序断下,检查一些值,接着再让程序继续执行。事实上,大部 分的断下并不是我们所希望的,我们只希望在某些条件下让程序断下。这时,条件断点就可以大大提高你的效率,节省你的时间。条件断点的命令如下,在后面的例 子中会有示例。
6.5条件断点
break ...if COND
COND是一个布尔条件表达式,语法与C语言中的一样。条件断点与一般的断点不同之处是每当程序执行到断点处,都要计算条件表达式,如果为真,程序才会断下,否则程序会一直执行下去。
7.其它断点操作
GDB给每个断点赋上一个整数数字,这个数字在操作断点时起到重要作用,它实际上就代表相应的断点。GDB中的断点有四种状态:
有效(Enabled)
禁止(Disabled)
一次有效(Enabled once)
有效后删除(Enabled for deletion)
在上面的四个状态有效和禁止都很好理解,禁止就是让断点暂时失效。一次有效就是当程序在此断点断下后,断点状态自动变为禁止状态。有效后删除就是当程序在此断点断下后,断点被删除。实际上,后两种状态一般不会碰到。
当你设置一个断点后,它的确省状态是有效。你可以用enable和disable
指令来设置断点的状态为有效或禁止。例如,如果你想禁止2号断点,可以用下面的
指令:
disable 2
相应的,如果想删除2号断点,可以有下面的
指令:
delete 2
8.设置监视点=== watch
当你调试一个很大的程序,并且在跟踪一个关键的变量时,发现这个变量不知在哪儿被改动过,如何才能找到改动它的地方。这时你可以使用watch命令。简单地说,监视点可以让你监视某个表达式或变量,当它被读或被写时让程序断下。watch命令的用法如下:
watch EXPRESSION
watch
指令是监视被写的,当你想监视某个表达式或变量被读的话,需要使用rwatch
指令,具体用法是一样的。要注意的是,监视点有硬件和软件 两种方式,如果可能Linux尽可能用硬件方式,因为硬件方式在速度上要大大快于软件方式。软件方式由于要在每次执行一条
指令后都要检查所要监视的值是否 被改变,因此它的执行速度会大大降低。同时它也无法设置成被读时让程序断下,因为读操作不会改变值,所以GDB无法检测到读操作。幸运的是,目前的PC机 基本都支持硬件方式。如果你想确认一下你的机器是否支持硬件,你可以在调试程序时用watch设置一个监视点,如果GDB向你显示:
Hardware watchpoint NUM: EXPR
那么你可以放心了,你的机器支持硬件方式。
9.检查数据
最常用的检查数据的方法是使用print命令。
print exp
print
指令打印exp表达式的值。却省情况下,表达式的值的打印格式依赖于它的数据类型。但你可以用一个参数/F来选择输出的打印格式。F是一 个代表某种格式的字母,详细可参考输出格式一节。表达式可以是常量,变量,函数调用,条件表达式等。但不能打印宏定义的值。表达式exp中的变量必须是全 局变量或当前堆栈区可见的变量。否则GDB会显示象下面的一条信息:
No symbol "varible" in current context
10.修改变量值
在调试程序时,你可能想改变一个变量的值,看看在这种情况下会发生什么。用set
指令可以修改变量的值: set varible=value 例如你想将一个变量tmp的值赋为10,
set tmp=10
11.检查内存值
检查内存值的
指令是x,x是examine的意思。用法如下:
x /NFU ADDR
其中N代表重复数,F代表输出格式(见2.13),U代表每个数据单位的大小。U可以去如下值:
b:字节(byte)
h:双字节数值
w:四字节数值
g:八字节数值
因此,上面的
指令可以这样解释:从ADDR地址开始,以F格式显示N个U数值。例如:
x/4ub 0x4000
会以无符号十进制整数格式(u)显示四个字节(b),0x4000,0x4001,0x4002,0x4003。
12.输出格式
缺省情况下,输出格式依赖于它的数据类型。但你可以改变输出格式。当你使用print命令时,可以用一个参数/F来选择输出的打印格式。F可以是以下的一些值:
'x' 16进制整数格式
'd'有符号十进制整数格式
'u'无符号十进制整数格式
'f'浮点数格式
13.单步执行
指令 单步执行
指令有两个step和next。Step可以让你跟踪进入一个函数,而next
指令则不会进入函数。
14.继续执行
指令 当程序被断下后,你查看了所需的信息后,你会希望程序执行下去,输入continue, 程序会继续执行下去。
15.帮助
指令help
在GDB中,如果想知道一条
指令的用法,最方便的方法是使用help。使用方法很简单,在help后跟上
指令名。例如,想知道list
指令用法,输入
help list