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

本文介绍如何使用GDB调试器对程序进行调试,包括启动和退出GDB、显示和查找源程序代码、执行程序和获得帮助、设置和管理断点等核心功能。

一,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 nuset 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没有被加上。

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值