您的位置:首页 > 运维架构 > Linux

Linux之gdb调试器——“撕破现象看本质”

2018-02-09 09:20 253 查看

一,gdb简介

gdb可以对源文件“预处理、编译、汇编、链接”后生成的可执行文件进行调试。以以下程序(test.c)为例:

#include<stdio.h>

int get_sum(int n)
{
int sum=0,i;
for(i=0;i<n;++i)
sum+=i;
return sum;
}
int main()
{
int i=100,result;
result=get_sum(i);
printf("1+2+……+%d=%d\n",i,result);
return 0;
}


在vim中,切换到末行模式,输入
set nu
set number
即可显示代码行号。





二,启动和退出gdb

使用gcc编译器编译test.c,需要使用-g选项以产生gdb调试所需的符号信息。

[shell]$gcc -g test.c -o test
//生成可执行文件



根据我们的数学知识,1+2+……+100=5500,也就是说,这个结果不是我们想要的。那到底是什么原因呢?在我们编译的时候,编译器并没有报错,也没有给出任何的警告信息,这表明我们的代码并没有语法错误,那么,我们的程序肯定出现了逻辑上的错误。

那么,现在就到了gdb大显身手的时候了!!!

我们将可执行文件test载入gdb调试器中:

[shell]$gdb test
//载入test



启动gdb时,同时会出现一段版权说明,然后是gdb的提示符(gdb)。使用-q选项可以关闭版权说明。



当然,也可以直接进入gdb,再使用file命令载入文件:



使用quit命令即可退出gdb。



若程序正在调试过程中退出,则会出现提示:



输入“y”即可。

三,显示、查找源程序代码

list命令用于列出程序的源代码,

(gdb)list    //从行1开始,执行命令每次显示10行代码


(gdb)list 5,10    //显示行5到行10的代码




(gdb)list get_sum  //列出函数get_sum周围的代码




(gdb)list test.c:5,10


//在调试多个文件时,显示某个文件某些行的代码


在调试时,仍然可以使用shell命令:

[shell]$shell ls




search和forward都可以用来从当前行向后查找第一个匹配的字符串。

reverse-search用来从当前行向前查找第一个匹配的字符。



四,执行程序和获得帮助

在载入可执行文件test后,使用run命令可以执行该程序:



使用help可以查看帮助文档:

(gdb)help list
//查看list的帮助信息

(gdb)help all
//查看gdb所以命令的帮助信息

五,设置和管理断点

在调试程序时,我们很希望能在程序运行的过程中实时的“监视”各个变量的值。但程序执行的过程是“一步”就完成的或时间相当快,因此,我们就需要在任何我们想要的“监视”的地方设置断点。以此,程序在运行时就会停在这些断点处,我们可以”监视“各个变量、函数、表达式的值。

在gdb调试器中,设置断点的命令为break:

1,以行号设置断点

(gdb)break 8




Breakpoint 1    //断点编号:断点1


0x400544    //断点所在内存地址


file test.c line 8    //表示断点所处的位置(哪个文件哪一行)


执行run命令,程序会停止在第8行,也就是我们设置的Breakpoint 1处。



2,以函数名设置断点

同样是使用break命令,我们可以在某个函数处设置断点:

(gdb)break get_sum    //在函数get_sum处设置断点


执行run命令:



正如我们所料,程序停在了函数get_sum处。

3,以条件、表达式设置断点

以“条件”设置断点

(gdb)break 行号或函数名  if  条件


(gdb)break 8 if i==99




由图,程序停在了行8
sum+=i
处。使用
print i
用来查看此时i的值,结果显示i=99。

还有break还可以在某个表达式设置断点。

watch 条件表达式


(gdb)watch i==99




反馈信息提示我们”此时尚未定义变量i”,所以创建失败。为了解决这个问题,我们需要在i被定义后设置一个断点,当程序停留在此段点时,就可以以表达式
i==99
设置断点了。



首先,我们使用
(gdb)break 6


在行6处设置一个断点,因为此时i已被定义。

之后,运行命令
(gdb)run


程序暂停在行6。这是我们设置断点的好时候!
(gdb)watch i==99


,在表达式
i==99
处成功设置了断点。
(gdb)continue


程序执行直到
i==99
为止。使用
print i
监视I的值,显然,i=99。
print sum
监视sum的值sum的值为4851



这时,让继续运行
sum+=i
,之后sum的值变为4950,再继续下去,程序执行结束。此时,程序的逻辑性错误已经很明显——100没有被加上。
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签:  调试 linux gdb