springwinter00 2010-05-13
gdb的命令很多,本文不会全部介绍,仅会介绍一些最常用的。在介绍之前,先介绍gdb中的一个非常有用的功能:补齐功能。它就如同linux下 shell中的命令补齐一样。当你输入一个命令的前几个字符,然后输入tab键,如果没有其它命令的前几个字符与此相同,shell将补齐此命令。如果有其它命令的前几个字符与此相同,你会听到一声警告声,再输入tab键,shell将所有前几个字符与此相同的命令全部列出。而gdb中的补齐功能不仅能补齐gdb命令,而且能补齐参数。
本文将先介绍常用的命令,然后结合一个具体的例子来演示如何实际使用这些命令。下面的所有命令除了第一条启动gdb命令是在shell下输入的,其余都是gdb内的命令。大部分gdb内的命令都可以仅输入前几个字符,只要不与其它指令冲突。如quit可以简写为q,因为以q打头的命令只有quit。list可以简写为l,等等。
1.启动gdb
你可以输入gdb来启动gdb
程序
。gdb程序有许多参数,在此没有必要详细介绍,但一个最为常用的还是要介绍的:如果你已经编译好一个程序,我们假设文件名为hello,你想用gdb调试它,可以输入gdbhello来启动gdb并载入你的程序。如果你仅仅启动了gdb,你必须在启动后,在gdb中再载入你的程序。
2.载入程序===file
在gdb内,载入程序很简单,使用file命令。如filehello。当然,
程序
的路径名要正确。
退出gdb===quit
在gdb的命令方式下,输入quit,你就可以退出gdb。你也可以输入'c-d'来退出gdb。
3.运行程序===run
当你在gdb中已将要调试的程序载入后,你可以用run命令来执行。如果你的
程序
需要参数,你可以在run指令后接着输入参数,就象你在shell下执行一个需要参数的命令一样。
4.查看程序信息===info
info指令用来查看程序的信息,当你用helpinfo查看帮助的话,info指令的参数足足占了两个屏幕,它的参数非常多,但大部分不常用。我用info指令最多的是用它来查看断点信息。
4.1查看断点信息
infobr
br是断点break的缩写,记得gdb的补齐功能吧。用这条指令,你可以得到你所设置的所有断点的详细信息。包括断点号,类型,状态,内存地址,断点在源程序中的位置等。
4.2查看当前源程序
infosource
4.3查看堆栈信息
infostack
用这条指令你可以看清楚程序的调用层次关系。
4.4查看当前的参数
infoargs
5.列出源一段源
程序
===list
5.1列出某个函数
listfunction
.2以当前源文件的某行为中间显示一段源程序
listlinenum
5.3接着前一次继续显示
list
5.4显示前一次之前的源程序
list-
5.5显示另一个文件的一段程序
listfilename:function或listfilename:linenum
6.设置断点===break
现在我们将要介绍的也许是最常用和最重要的命令:设置断点。无论何时,只要你的
程序
已被载入,并且当前没有正在运行,你就能设置,修改,删除断点。设置断点的命令是break。有许多种设置断点的方法。如下:
6.1在函数入口设置断点
breakfunction
6.2在当前源文件的某一行上设置断点
breaklinenum
6.3在另一个源文件的某一行上设置断点
breakfilename:linenum
6.4在某个地址上设置断点,当你调试的
程序
没有源程序是,这很有用
break*address
除此之外,设置一个断点,让它只有在某些特定的条件成立时程序才会停下,我们可以称其为条件断点。这个功能很有用,尤其是当你要在一个程序会很多次执行到的地方设置断点时。如果没有这个功能,你必须有极大的耐心,加上大量的时间,一次一次让程序断下,检查一些值,接着再让程序继续执行。事实上,大部分的断下并不是我们所希望的,我们只希望在某些条件下让程序断下。这时,条件断点就可以大大提高你的效率,节省你的时间。条件断点的命令如下,在后面的例子中会有示例。
6.5条件断点
break...ifcond
7.其它断点操作
gdb给每个断点赋上一个整数数字,这个数字在操作断点时起到重要作用,它实际上就代表相应的断点。gdb中的断点有四种状态:
有效(enabled)
禁止(disabled)
一次有效(enabledonce)
有效后删除(enabledfordeletion)
在上面的四个状态有效和禁止都很好理解,禁止就是让断点暂时失效。一次有效就是当程序在此断点断下后,断点状态自动变为禁止状态。有效后删除就是当程序在此断点断下后,断点被删除。实际上,后两种状态一般不会碰到。
当你设置一个断点后,它的确省状态是有效。你可以用enable和disable指令来设置断点的状态为有效或禁止。例如,如果你想禁止2号断点,可以用下面的指令:
disable2
相应的,如果想删除2号断点,可以有下面的指令:
delete2
8.设置监视点===watch
当你调试一个很大的程序,并且在跟踪一个关键的变量时,发现这个变量不知在哪儿被改动过,如何才能找到改动它的地方。这时你可以使用watch命令。简单地说,监视点可以让你监视某个表达式或变量,当它被读或被写时让
程序
断下。watch命令的用法如下:
watchexpression
watch指令是监视被写的,当你想监视某个表达式或变量被读的话,需要使用rwatch指令,具体用法是一样的。要注意的是,监视点有硬件和软件两种方式,如果可能linux尽可能用硬件方式,因为硬件方式在速度上要大大快于软件方式。软件方式由于要在每次执行一条指令后都要检查所要监视的值是否被改变,因此它的执行速度会大大降低。同时它也无法设置成被读时让
程序
断下,因为读操作不会改变值,所以gdb无法检测到读操作。幸运的是,目前的pc机基本都支持硬件方式。如果你想确认一下你的机器是否支持硬件,你可以在调试程序时用watch设置一个监视点,如果gdb向你显示:
hardwarewatchpointnum:expr
.检查数据
最常用的检查数据的方法是使用print命令。
printexp
print指令打印exp表达式的值。却省情况下,表达式的值的打印格式依赖于它的数据类型。但你可以用一个参数/f来选择输出的打印格式。f是一个代表某种格式的字母,详细可参考输出格式一节。表达式可以是常量,变量,函数调用,条件表达式等。但不能打印宏定义的值。表达式exp中的变量必须是全局变量或当前堆栈区可见的变量。否则gdb会显示象下面的一条信息:
nosymbol"varible"incurrentcontext
10.修改变量值
在调试
程序
时,你可能想改变一个变量的值,看看在这种情况下会发生什么。用set指令可以修改变量的值:
setvarible=value
例如你想将一个变量tmp的值赋为10,
settmp=10
11.检查内存值
检查内存值的指令是x,x是examine的意思。用法如下:
x/nfuaddr
其中n代表重复数,f代表输出格式(见2.13),
f可以是以下的一些值:
'x'16进制整数格式
'd'有符号十进制整数格式
'u'无符号十进制整数格式
'f' 浮点数格式u代表每个数据单位的大小。u可以去如下值:
b:字节(byte)
h:双字节数值
w:四字节数值
g:八字节数值
因此,上面的指令可以这样解释:从addr地址开始,以f格式显示n个u数值。例如:
x/4ub0x4000
会以无符号十进制整数格式(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指令用法,输入
helplist