查看运行时数据
——————3354 -
调试程序时,程序停止时,可以使用print命令(命令简称为p )或同义命令inspect查看当前程序的执行数据。 print命令的格式如下:
打印浏览器
print /f expr
expr是表达式,是正在调试的程序的语言表达式。 (GDB可以调试多种编程语言。 ) f是输出的形式。 例如,如果以十六进制格式输出表达式,则为/x。
一、表达式
与许多GDB指令一样,print可以接受GDB基于当前程序运行的数据计算的表达式。 既然是表达式,则为当前程序执行的常数、变量、函数等内容。 遗憾的是,GDB无法使用程序中定义的宏。
表达式语法应该是目前调试的语言语法,而C/C是大众型语言,所以本文的例子都是关于C/C的。 (稍后将介绍在GDB中调试其他语言的章节。)
表达式中有几个GDB支持的操作符,可以使用任一种语言。
@
是与数组相关的操作符,稍后将详细说明。
:
指定文件或函数中的变量。
{type} addr
指向内存地址addr的类型表示类型为type的对象。
二、程序变量
在GDB中,可以随时查看以下三个变量的值:
1、全局变量(所有文件可见) ) ) ) )。
2、静态全局变量(在当前文件中可见) ) ) ) )。
3、局部变量(当前在作用域中可见) ) ) ) ) )。
如果您的局部变量与全局变量发生冲突(即重复),局部变量通常会隐藏全局变量。 也就是说,如果一个全局变量和一个函数中的局部变量具有相同的名称,并且当前停止点位于函数中,则print显示的变量值是函数中局部变量的值。 如果要在此查看全局变量的值,请使用“:”操作符。
file:variable
function:variable
在这种形式下,可以指定要显示的变量位于哪个文件中,以及位于哪个函数中。 例如,看看文件f2.c中全局变量x的值。
gdb ) p 'f2.c':x
当然,“:3360”操作员会与c操作员发生冲突,GDB会自动识别“:3360”是否为c操作员,因此在调试c程序时不用担心发生异常。
另外,请注意,如果在编译程序时打开了优化选项,则在GDB中调试优化的程序时,可能无法访问某些变量,或者可能会获取值并返回错误代码。 这很正常。 优化程序会修改你的程序,整理你程序中的语句顺序,去除无意义的变量等,所以对于GDB调试这样的程序,运行时的指令和你做的指令不一样,或者产生了你无法想象的结果要解决这一问题,在编译程序时必须关闭编译优化。 一般来说,大多数编译器都支持编译优化开关。 例如,在GNU的C/C编译器GCC中,可以使用-gstabs选项解决此问题。 关于编译器的参数,也请参照编译器的使用说明书。
三、数组
在某些情况下,需要检查连续内存区域的值。 数组的一部分、动态分配的数据的大小等。 可以使用GDB中的“@”操作符。 “@”的左侧是第一个内存的地址值,“@”的右侧是内存的长度。 例如,你的程序中有以下语言。
int*array=(int* ) malloc (len * sizeof ) int );
因此,在GDB调试期间,以下命令可以显示此动态数组的可能值:
p *array@len
@的左边是数组开头地址的值,即变量array所指定的内容,右边是数据的长度,保存在变量len中,其输出结果大致如下:
(gdb ) p *array@len
$1={2、4、6、8、10、12、14、16、18、20、22、26、28、30、32、34、36、38、40}
如果是静态数组,则可以直接打印数组名称来显示数组中所有数据的内容。
四、输出格式
一般来说,GDB会根据变量的类型输出变量的值。但你也可以自定义GDB的输出的格式。例如,你想输出一个整数的十六进制,或是二进制来查看这个整型变量的中的位的情况。要做到这样,你可以使用GDB的数据显示格式:
x 按十六进制格式显示变量。
d 按十进制格式显示变量。
u 按十六进制格式显示无符号整型。
o 按八进制格式显示变量。
t 按二进制格式显示变量。
a 按十六进制格式显示变量。
c 按字符格式显示变量。
f 按浮点数格式显示变量。
(gdb) p i
$21 = 101
(gdb) p/a i
$22 = 0x65
(gdb) p/c i
$23 = 101 'e'
(gdb) p/f i
$24 = 1.41531145e-43
(gdb) p/x i
$25 = 0x65
(gdb) p/t i
$26 = 1100101
五、查看内存
你可以使用examine命令(简写是x)来查看内存地址中的值。x命令的语法如下所示:
x/<n/f/u> <addr>
n、f、u是可选的参数。
n 是一个正整数,表示显示内存的长度,也就是说从当前地址向后显示几个地址的内容。
f 表示显示的格式,参见上面。如果地址所指的是字符串,那么格式可以是s,如果地十是指令地址,那么格式可以是i。
u 表示从当前地址往后请求的字节数,如果不指定的话,GDB默认是4个bytes。u参数可以用下面的字符来代替,b表示单字节,h表示双字节,w表示四字节,g表示八字节。当我们指定了字节长度后,GDB会从指内存定的内存地址开始,读写指定字节,并把其当作一个值取出来。
<addr>表示一个内存地址。
n/f/u三个参数可以一起使用。例如:
命令:x/3uh 0x54320 表示,从内存地址0x54320读取内容,h表示以双字节为一个单位,3表示三个单位,u表示按十六进制显示。
六、自动显示
你可以设置一些自动显示的变量,当程序停住时,或是在你单步跟踪时,这些变量会自动显示。相关的GDB命令是display。
display <expr>
display/<fmt> <expr>
display/<fmt> <addr>
expr是一个表达式,fmt表示显示的格式,addr表示内存地址,yedcb用display设定好了一个或多个表达式后,只要你的程序被停下来,GDB会自动显示你所设置的这些表达式的值。
格式i和s同样被display支持,一个非常有用的命令是:
display/i $pc
$pc是GDB的环境变量,表示着指令的地址,/i则表示输出格式为机器指令码,也就是汇编。于是当程序停下后,就会出现源代码和机器指令码相对应的情形,这是一个很有意思的功能。
下面是一些和display相关的GDB命令:
undisplay <dnums...>
delete display <dnums...>
删除自动显示,dnums意为所设置好了的自动显式的编号。如果要同时删除几个,编号可以用空格分隔,如果要删除一个范围内的编号,可以用减号表示(如:2-5)
disable display <dnums...>
enable display <dnums...>
disable和enalbe不删除自动显示的设置,而只是让其失效和恢复。
info display
查看display设置的自动显示的信息。GDB会打出一张表格,向你报告当然调试中设置了多少个自动显示设置,其中包括,设置的编号,表达式,是否enable。
<-上一页 下一页->
(版权所有,转载时请注明作者和出处)