Linux学习之gdb的使用

目录

1.Debug与Release模式

如何证明debug是可以被调试的?

2.Linux调试器-gdb使用 

gdb调试的指令

指令一:list(l) 查看源代码

  ​编辑      ​编辑 命令二:run(r)运行程序

  命令三:breakpoint(b)设置断点

 命令四:infobreak(info)查看断点

 命令五:delete breakpoint(d)删除断点

命令六:启用/禁用断点enable /disable breakpoint

命令七:next(n)逐过程运行

命令八:step(s)逐语句运行

命令九: printf 变量(p 变量)查看变量

命令十: displayundisplay 变量       常显示查看变量(跟踪变量)

命令十一:undisplay 跟踪编号       取消常显示(取消跟踪)

命令十二:until  行号     执行中跳至x行

命令十三:finish 直接运行结束

 命令十四:continue(c) 当前位置开始连续而非单步执行程序

命令十五:bt   查看调用堆栈

 命令十六:set var 变量    修改变量


1.Debug与Release模式

在学习c++时我们就已经了解到这两种编译模式。

Debug 通常称为调试版本,是通过一系列编译选项的配合,编译的结果通常包含调试信息,而且不做任何优化,以为开发人员提供 强大的应用程序调试能力。

Release:Release通常称为 发布版本,是为用户使用的,一般客户不允许在发布版本上进行调试。所以不保存调试信息,同时,它往往进行了各种优化,以期达到代码最小和速度最优

  总的来看,Debug与release是两种代码编译模式,Debug下代码可以被调试,而Release下会将代码优化

如何证明debug是可以被调试的?

     1.Debug模式下可以被调试主要是因为在编译后会添加Debug信息,从而使得文件可以被调试。

对于Release是没有这些信息的,仔细发现两种方式下编译的可执行程序大小是不一样的

ll 文件名//查看两种方式下的可执行程序大小

 2.我们还可以查看可执行程序里面的内容,很容易看出两者是存在差异的:

readelf -a 文件名 //可以查看二进制文件
readelf -S 文件名 | grep -i debug //通过管道筛选出是否有debug信息

 Linux学习之gdb的使用_第1张图片

如果一份代码要进行调试,这份代码的发布模式必须是Debug模式的,而当一份代码要进行发布时,测试人员进行测试的是Release版本,测试完成之后就会上线。

2.Linux调试器-gdb使用 

当我们学会了编译代码时,就想知道代码书写错误,程序报错如何去调试,对于Linux提供了gdb用来调试:

GDB是GNU symbolic debugger的缩写,是一款常用的程序调试器,主要用于调试C、C++、Go、Objective-C、OpenCL、Ada等编程语言编写的程序。

它可以帮助我们完成以下四个方面的功能:

  1. 启动你的程序,可以按照你的自定义的要求随心所欲地运行程序。
  2. 在某个指定的地方或条件下暂停程序。
  3. 当程序被停住时,可以检查此时你的程序中所发生的事。
  4. 在程序执行过程中修改程序中的变量或条件,将一个bug产生的影响修正从而测试其他bug。

其次我们还需要知道的是在linux环境下编译默认都是Release模式下,故无法被调试。我们需要借助gdb,那么我们如何调试呢?

gdb调试的指令

首先对于调试工具gdb也为我们提供了多种调试方法

调试命令:

Linux学习之gdb的使用_第2张图片退出: ctrl + d 或 quit 。

我们现在以一个求某个数的累加和的.c程序为例,在下面实验我们去如何调试:

对于gdb默认一般都是安装的,我们也可以查看是否拥有gdb:

gdb --v

查看拥有gdb之后,我们先尝试去gdb调试,先将我们的文件直接gcc编译生成可执行文件,之后我们直接对我们想要调试的可执行程序进行gdb 文件名:

gdb 文件名

之后我们就进入了gdb下命令窗口:

 可以看到对于我们想要调试的程序,这里会说对于我这个可执行文件(code.c),是没有debug的信息被发现,当前是无法被调试的,即当前调试指令时无效的。

这里对于Linux下的gcc 编译工具默认是在Release模式下编译,编译生成的文件是无法被调试的,故会报错无调试信息。那么如何去增加debug信息呢?

我们需要在编译生成可执行程序时增加编译选项:

gcc -g 文件 -o 目标文件 //添加-g选项,以debug方式编译文件

之后我们就可以调试该文件:

指令一:list(l) 查看源代码

l按gdb的方式显示代码                                 l  0  从开头开始打印

Linux学习之gdb的使用_第3张图片Linux学习之gdb的使用_第4张图片

再次回车时(gdb会自动记录上一个命令),显示后面的源码,直到全部,此时会提示我们多少行已全部显示

  Linux学习之gdb的使用_第5张图片      Linux学习之gdb的使用_第6张图片 命令二:run(r)运行程序

直接r可以看到程序直接被运行完,结果出现

 

  命令三:breakpoint(b)设置断点

b 行号  //该行处设置断点

 设置完毕会返回关于断点的信息。

对于多源文件,gdb也可以打断点

b 文件名:行号

 其次我们还可以直接给出函数名来设置断点

b 函数名  //默认打断点在函数的入口处
b 文件名:函数名

 命令四:infobreak(info)查看断点

 可以看到在第六行设置一个断点,还有其地址,类型等。

 命令五:delete breakpoint(d)删除断点

d 断点编号

虽然打断点可以直接用行号和函数名,但是删除断点必须要用他的断点编号,所谓的断点编号就是在我们设置断点后返回的断点信息中的NUM,利用info也可以查看到。

Linux学习之gdb的使用_第7张图片

 其中对于一个周期的调试下,断点的编号是一直递增的,当我们退出调试后,重新在调试即开启下一个周期,之前的都会被清除。

命令六:启用/禁用断点enable /disable breakpoint

对于一个断点,我们目前不想使用它,但不取消它,用来记录我们调试的区域,可以禁用它让他不起作用,其次我们也可以查看到一个断点的状态(y代表启用,n代表禁止)

Linux学习之gdb的使用_第8张图片

现在我么来禁用一个端点

disable 断点编号

Linux学习之gdb的使用_第9张图片再开启它:

enable 断点编号

Linux学习之gdb的使用_第10张图片

命令七:next(n)逐过程运行

 对于断点设置好之后就可以run了,程序直接跑到断点处执行,类比于vs的F10,之后断点处输入n就可以逐过程(一行一行的运行,遇到空行直接跳过)的运行程序,

Linux学习之gdb的使用_第11张图片

可以看到运行到了下一行第7行,再次n,又运行到下一行,直到退出。

命令八:step(s)逐语句运行

所谓逐语句区别于逐过程,逐语句执行更加的严密仔细,一个一个语句运行,遇到函数直接进入函数内部,s之后,继续执行:

Linux学习之gdb的使用_第12张图片

可以看到断点处开始执行,遇到函数,进入函数内部。

命令九: printf 变量(p 变量)查看变量

在上述逐语句的过程中,我们此时再循环内,此时就可以查看一些变量的值:

Linux学习之gdb的使用_第13张图片

例如这里循环了四次,累加了四次,此时 i=4,sum =6,之后再运行再查看,就可以观察到变量的变化了。

当然我们也可以查看变量的地址:

命令十: displayundisplay 变量       常显示查看变量(跟踪变量)

对于上述p查看变量每次查看我都要输入,怎样可以跟vs的监视窗口的 效果一样的,长时间显示我们变量的变化,利用display我们也可以做到。、

Linux学习之gdb的使用_第14张图片

 可以看到每一next逐过程执行时都会为我们自动打印我们所要看的变量的值。

命令十一:undisplay 跟踪编号       取消常显示(取消跟踪)

对于我们不长时间查看的变量,我们不能直接undisplay 变量来取消,仔细发现在我们每一次跟踪变量时,每一次显示都可以看到变量前有一个编号,而取消编号才能做取消跟踪。

Linux学习之gdb的使用_第15张图片Linux学习之gdb的使用_第16张图片

可以看到取消掉了跟踪,不再显示变量。

命令十二:until  行号     执行中跳至x行

由于我此时在循环里,且循环比较大,一直next循环结束太过离谱,英雌我们可以直接跳至程序某一行。

Linux学习之gdb的使用_第17张图片

Linux学习之gdb的使用_第18张图片

 现在我跳至程序的第7行,打印结果,此时代码是抬到了20行,可以看到如果遇到断点会跳到断点处,若没有断点此时会跳至第7行。

故跳出循环有两种方式,一是设置断点,再run或者until眺出去,二是不设置断点直接跳出去。

命令十三:finish 直接运行结束

Linux学习之gdb的使用_第19张图片

可以看到直接到程序结束,打印了结果

 命令十四:continue(c) 当前位置开始连续而非单步执行程序

简单说可以理解为从一个断点跳至另一个断点处。

Linux学习之gdb的使用_第20张图片

命令十五:bt   查看调用堆栈

在运行过程中,查看函数的调用顺序,这里先调用主函数再调用addtop,因为这里是以栈的方式,故是倒着的顺序。

Linux学习之gdb的使用_第21张图片

 命令十六:set var 变量    修改变量

我们可以在调试的过程中去修改变量达到我们想要的调试情况:

如这里i我们可以直接修改为10,查看我们改变时运行的效果。

你可能感兴趣的:(linux,学习,运维)