用 gdb 调试 GCC 程序.docx

上传人:b****4 文档编号:5500678 上传时间:2022-12-17 格式:DOCX 页数:10 大小:19.44KB
下载 相关 举报
用 gdb 调试 GCC 程序.docx_第1页
第1页 / 共10页
用 gdb 调试 GCC 程序.docx_第2页
第2页 / 共10页
用 gdb 调试 GCC 程序.docx_第3页
第3页 / 共10页
用 gdb 调试 GCC 程序.docx_第4页
第4页 / 共10页
用 gdb 调试 GCC 程序.docx_第5页
第5页 / 共10页
点击查看更多>>
下载资源
资源描述

用 gdb 调试 GCC 程序.docx

《用 gdb 调试 GCC 程序.docx》由会员分享,可在线阅读,更多相关《用 gdb 调试 GCC 程序.docx(10页珍藏版)》请在冰豆网上搜索。

用 gdb 调试 GCC 程序.docx

用gdb调试GCC程序

用gdb调试GCC程序

Linux中包含有一个很有用的调试工具--gdb(GNUDebuger),它可以用来调试C和C++程序,功能不亚于Windows下的许多图形界面的调试工具。

和所有常用的调试工具一样,gdb提供了以下功能:

 #监视程序中变量的值

 #在程序中设置断点

 #程序的单步执行

在使用gdb前,必须先载入可执行文件,因为要进行调试,文件中就必须包含调试信息,所以在用gcc或cc编译时就需要用-g参数来打开程序的调试选项。

调试开始时,必须先载入要进行调试的程序,可以用以下两种方式:

 *在启动gdb后执行以下命令:

   file可执行文件路径

 *在gdb启动时就载入程序:

   gdb可执行文件路径

载入程序后,接下来就是要进行断点的设置,要监视的变量的添加等工作,下面对在这个过程中常会用到的命令逐一进行介绍:

基本gdb命令.

file装入想要调试的可执行文件.

kill终止正在调试的程序.

list列出产生执行文件的源代码的一部分.

next执行一行源代码但不进入函数内部.

step执行一行源代码而且进入函数内部.

run执行当前被调试的程序

quit终止gdb

watch使你能监视一个变量的值而不管它何时被改变.

break在代码里设置断点,这将使程序执行到这里时被挂起.

make使你能不退出gdb就可以重新产生可执行文件.

shell使你能不离开gdb就执行UNIXshell命令.

命令详解

 *list:

显示程序中的代码,常用使用格式有:

    list

      输出从上次调用list命令开始往后的10行程序代码。

    list-

      输出从上次调用list命令开始往前的10行程序代码。

    listn

      输出第n行附近的10行程序代码。

    listfunction

      输出函数function前后的10行程序代码。

 *forward/search:

从当前行向后查找匹配某个字符串的程序行。

使用格式:

    forward/search字符串

  查找到的行号将保存在$_变量中,可以用print$_命令来查看。

 *reverse-search:

和forward/search相反,向前查找字符串。

使用格式同上。

 *break:

在程序中设置断点,当程序运行到指定行上时,会暂停执行。

使用格式:

    break要设置断点的行号

 *tbreak:

设置临时断点,在设置之后只起作用一次。

使用格式:

    tbreak要设置临时断点的行号

 *clear:

和break相反,clear用于清除断点。

使用格式:

    clear要清除的断点所在的行号

 *run:

启动程序,在run后面带上参数可以传递给正在调试的程序。

 *awatch:

用来增加一个观察点(addwatch),使用格式:

    awatch变量或表达式

  当表达式的值发生改变或表达式的值被读取时,程序就会停止运行。

 *watch:

与awatch类似用来设置观察点,但程序只有当表达式的值发生改变时才会停止运行。

使用格式:

    watch变量或表达式

  需要注意的是,awatch和watch都必须在程序运行的过程中设置观察点,即可运行run之后才能设置。

 *commands:

设置在遇到断点后执行特定的指令。

使用格式有:

    commands

      设置遇到最后一个遇到的断点时要执行的命令

    commandsn

      设置遇到断点号n时要执行的命令

  注意,commands后面跟的是断点号,而不是断点所在的行号。

  在输入命令后,就可以输入遇到断点后要执行的命令,每行一条命令,在输入最后一条命令后输入end就可以结束输入。

 *delete:

清除断点或自动显示的表达式。

使用格式:

    delete断点号

 *disable:

让指定断点失效。

使用格式:

    disable断点号列表

  断点号之间用空格间隔开。

 *enable:

和disable相反,恢复失效的断点。

使用格式:

    enable断点编号列表

 *ignore:

忽略断点。

使用格式:

    ignore断点号忽略次数

 *condition:

设置断点在一定条件下才能生效。

使用格式:

    condition断点号条件表达式

 *cont/continue:

使程序在暂停在断点之后继续运行。

使用格式:

    cont

      跳过当前断点继续运行。

    contn

      跳过n次断点,继续运行。

  当n为1时,cont1即为cont。

 *jump:

让程序跳到指定行开始调试。

使用格式:

    jump行号

 *next:

继续执行语句,但是跳过子程序的调用。

使用格式:

    next

      执行一条语句

    nextn

      执行n条语句

 *nexti:

单步执行语句,但和next不同的是,它会跟踪到子程序的内部,但不打印出子程序内部的语句。

使用格式同上。

 *step:

与next类似,但是它会跟踪到子程序的内部,而且会显示子程序内部的执行情况。

使用格式同上。

 *stepi:

与step类似,但是比step更详细,是nexti和step的结合。

使用格式同上。

 *whatis:

显示某个变量或表达式的数据类型。

使用格式:

    whatis变量或表达式

 *ptype:

和whatis类似,用于显示数据类型,但是它还可以显示typedef定义的类型等。

使用格式:

    ptype变量或表达式

 *set:

设置程序中变量的值。

使用格式:

    set变量=表达式

    set变量:

=表达式

 *display:

增加要显示值的表达式。

使用格式:

    display表达式

 *infodisplay:

显示当前所有的要显示值的表达式。

 *deletedisplay/undisplay:

删除要显示值的表达式。

使用格式:

    deletedisplay/undisplay表达式编号

 *disabledisplay:

暂时不显示一个要表达式的值。

使用格式:

    disabledisplay表达式编号

 *enabledisplay:

与disabledisplay相反,使用表达式恢复显示。

使用格式:

    enabledisplay表达式编号

 *print:

打印变量或表达式的值。

使用格式:

    print变量或表达式

  表达式中有两个符号有特殊含义:

$和$$。

  $表示给定序号的前一个序号,$$表示给定序号的前两个序号。

  如果$和$$后面不带数字,则给定序号为当前序号。

 *backtrace:

打印指定个数的栈帧(stackframe)。

使用格式:

    backtrace栈帧个数

 *frame:

打印栈帧。

使用格式:

    frame栈帧号

 *infoframe:

显示当前栈帧的详细信息。

 *select-frame:

选择栈帧,选择后可以用infoframe来显示栈帧信息。

使用格式:

    select-frame栈帧号

 *kill:

结束当前程序的调试。

*quit:

退出gdb。

 

gdb应用举例

本节用一个实例教你一步步的用gdb调试程序.被调试的程序相当的简单,但它展示了gdb的典型应用.

下面列出了将被调试的程序.这个程序被称为greeting,它显示一个简单的问候,再用反序将它列出.

#include

main()

{

charmy_string[]="hellothere";

my_print(my_string);

my_print2(my_string);

}

voidmy_print(char*string)

{

printf("Thestringis%s",string);

}

voidmy_print2(char*string)

{

char*string2;

intsize,i;

size=strlen(string);

string2=(char*)malloc(size+1);

for(i=0;i

string2[size-i]=string[i];

string2[size+1]=`';

printf("Thestringprintedbackwardis%s",string2);

}

用下面的命令编译它:

gcc–gtest.c-otest

这个程序执行时显示如下结果:

Thestringishellothere

Thestringprintedbackwardis

输出的第一行是正确的,但第二行打印出的东西并不是我们所期望的.我们所设想的输出应该是:

Thestringprintedbackwardiserehtolleh

由于某些原因,my_print2函数没有正常工作.让我们用gdb看看问题究竟出在哪儿,先键入如下命令:

gdbgreeting

--------------------------------------------------------------------------------

注意:

记得在编译greeting程序时把调试选项打开.

--------------------------------------------------------------------------------

如果你在输入命令时忘了把要调试的程序作为参数传给gdb,你可以在gdb提示符下用file命令来载入它:

(gdb)filegreeting

这个命令将载入greeting可执行文件就象你在gdb命令行里装入它一样.

这时你能用gdb的run命令来运行greeting了.当它在gdb里被运行后结果大约会象这样:

(gdb)run

Startingprogram:

/root/greeting

Thestringishellothere

Thestringprintedbackwardis

Programexitedwithcode041

这个输出和在gdb外面运行的结果一样.问题是,为什么反序打印没有工作?

为了找出症结所在,我们可以在my_print2函数的for语句后设一个断点,具体的做法是在gdb提示符下键入list命令三次,列出源代码:

(gdb)list

(gdb)list

(gdb)list

--------------------------------------------------------------------------------

技巧:

在gdb提示符下按回车健将重复上一个命令.

--------------------------------------------------------------------------------

第一次键入list命令的输出如下:

1#include

2

3main()

4{

5charmy_string[]="hellothere";

6

7my_print(my_string);

8my_print2(my_string);

9}

10

如果按下回车,gdb将再执行一次list命令,给出下列输出:

11my_print(char*string)

12{

13printf("Thestringis%s",string);

14}

15

16my_print2(char*string)

17{

18char*string2;

19intsize,i;

20

再按一次回车将列出greeting程序的剩余部分:

21size=strlen(string);

22string2=(char*)malloc(size+1);

23for(i=0;i

24string2[size-i]=string[i];

25string2[size+1]=`';

26printf("Thestringprintedbackwardis%s",string2);

27}

根据列出的源程序,你能看到要设断点的地方在第24行,在gdb命令行提示符下键入如下命令设置断点:

(gdb)break24

gdb将作出如下的响应:

Breakpoint1at0x139:

filegreeting.c,line24

(gdb)

现在再键入run命令,将产生如下的输出:

Startingprogram:

/root/greeting

Thestringishellothere

Breakpoint1,my_print2(string=0xbfffdc4"hellothere")atgreeting.c:

24

24string2[size-i]=string[i]

你能通过设置一个观察string2[size-i]变量的值的观察点来看出错误是怎样产生的,做法是键入:

(gdb)watchstring2[size-i]

gdb将作出如下回应:

Watchpoint2:

string2[size-i]

现在可以用next命令来一步步的执行for循环了:

(gdb)next

经过第一次循环后,gdb告诉我们string2[size-i]的值是`h`.gdb用如下的显示来告诉你这个信息:

Watchpoint2,string2[size-i]

Oldvalue=0`00'

Newvalue=104`h'

my_print2(string=0xbfffdc4"hellothere")atgreeting.c:

23

23for(i=0;i

这个值正是期望的.后来的数次循环的结果都是正确的.当i=10时,表达式string2[size-i]的值等于`e`,size-i的值等于1,最后一个字符已经拷到新串里了.

如果你再把循环执行下去,你会看到已经没有值分配给string2[0]了,而它是新串的第一个字符,因为malloc函数在分配内存时把它们初始化为空(null)字符.所以string2的第一个字符是空字符.这解释了为什么在打印string2时没有任何输出了.

现在找出了问题出在哪里,修正这个错误是很容易的.你得把代码里写入string2的第一个字符的的偏移量改为size-1而不是size.这是因为string2的大小为12,但起始偏移量是0,串内的字符从偏移量0到偏移量10,偏移量11为空字符保留.

为了使代码正常工作有很多种修改办法.一种是另设一个比串的实际大小小1的变量.这是这种解决办法的代码:

#include

main()

{

charmy_string[]="hellothere";

my_print(my_string);

my_print2(my_string);

}

my_print(char*string)

{

printf("Thestringis%s",string);

}

my_print2(char*string)

{

char*string2;

intsize,size2,i;

size=strlen(string);

size2=size-1;

string2=(char*)malloc(size+1);

for(i=0;i

string2[size2-i]=string[i];

string2[size]=`';

printf("Thestringprintedbackwardis%s",string2);

}

本文来自CSDN博客,转载请标明出处:

file:

///D:

/2009Linux实习/2009%20Linux%20实习/Gbd调试器/Linux%20下的%20gbd调试%20-%20tianhappy(城市旅行者)%20-%20CSDN博客.htm

展开阅读全文
相关资源
猜你喜欢
相关搜索

当前位置:首页 > 医药卫生

copyright@ 2008-2022 冰豆网网站版权所有

经营许可证编号:鄂ICP备2022015515号-1