目录
前言:
1 预备知识
2 gdb的使用
前言:
当我们Linux学到了这里的时候,我们大概会有一种感觉是,从VS2022转战Linux,写代码对我们来说是一种重新构建读写代码的一个过程,从文本编辑器,到文本编译器,再到今天的调试器gdb,读写代码的每个部分在Linux这里都是单独拉出来的,所以不免许多人会感受到困难,甚至于某些简单的代码在Linux这里都有点感觉晦涩难懂了,但是呢,难关总会过去的,咱们今天把gdb一看,我们就能再跨越代码的一大关卡 - 调试。
1 预备知识
首先引入第一个问题,我们平常在VS编译代码的时候,左上角的debug和release是非常显然的,我们可以自由选择编译模式,那么在Linux中,编译代码的模式是什么呢?
在linux中,gcc/g++编译代码默认是以release进行编译的,那么我们如何切换到debug模式呢?
只需要加 -g就可以:
这里是已经编译好了的,那么试着猜猜,哪个是debug版本,哪个是release版本的?
还是很好猜的,release版本的优化比debug厉害不说,debug也被称为调试版本,所以自然会存在一些调试信息,自然的,debug版本的大小比release版本的大。
那么我们如何看到调试信息呢?
输入以上命令即可,因为部分命令还没有涉及,这里先不做介绍。
以上就是调试信息,现在我们就该进入到调试了。
2 gdb的使用
首先,我们知道,在vs常用的技巧有,逐语句调试,逐过程调试,打断点,和断点配套的F5调试,监视窗口,跳转到指定行调试等。
那么我们在gdb里面要做的,也就是这些事。
首先进入调试很简单,就是gdb + 可执行文件。但是前提是已经用gcc -g生成了二进制的调试文件,此时才可以使用gdb进行调试。
进入之后,我们是不可能记得住我们所有的代码的,那么就需要我们将代码展示出来,此时用的指令是l,也就是list的意思,可以简写成l,后面+数字表示从哪里开始打印:
它的特点是默认打印10行,并且是打印该行数的上下文,所以这里打印了上下文:
并且gdb有一个特点就是,默认执行上次的命令,所以我们输入了一个l 5之后,就可以一直空格,直到:
这个的出现,代表已经打印完了,这里的l 6的数字并不是绝对数字,是相对的,我打印10行之后,l 6 代表的是10行之后的第6行。
还可以l 文件名:函数名,直接打印函数,也可以直接l 函数名:
好了,现在可以看到代码了,那么下一步是,如何打断点?
打断点用到的命令是Breakpoint,简称b,对应的操作有b 文件名:函数名/行号,或者直接b 函数名/行号:
那么断点就打好了,在VS里面,断点很显眼的来了个大红点,但是Linux中打了断点我们应该如何查看呢?
此时就要info (信息),简称为i,i b即可:
但是呢,因为主函数本质是代码块,所以打在主函数的断点就是打在主函数的第一条可执行语句上,所以有两个会重复。
那么断点有了,我们如何删除呢?删除用的是d,但是断点的名字是啥?欸~编号咯。
此时就删除成功了,我们再打断点看看:
欸?不难发现断点的名字是线性增长的,不存在回退的说法。
这是linux中断点的一个特性。
肯定会有人问的,Enb是什么意思?enable。代表是否可执行这个断点。
我们想要禁止一个断点只需要:
同理,希望它能使用只需要:
好了,基本的打断点我们会了,我们如何逐语句或者逐过程调试呢?
逐过程是:
next,下一步,简称为n,但是使用next的前提是要先run一下程序,不然程序跑不起来如何调试?
run就相当于F5,如果没有断点就是直接运行。
这里因为我是将断点打在了函数上,所以直接就运行了。
逐语句就是step,脚步,简称为s:
每s一下就会打印出执行的语句,如果超了,或者是程序没有run就会报以上的错误。
展示出来都是一样的,也是有自己的编号的,那么同理,undisplay也是需要编号的。
那么在VS里面还有断点之间互相跳动的,此时要用到的就是continue,继续,简称为c:
这样即可。
当然了,display是展示,调试的时候一直展示的意思,如果我们只是看一下,使用print,打印,简称p即可,此时$后面的数字就是打印的次数。
直接运行完一个函数不止可以逐过程,也可以用finish,代表,运行结束所在函数就停下来,也有until,比如我们进入了一个循环,想直接跳过就用until:
就像这样。
info local是查看局部栈帧变量的值,既然是栈帧,我们也可以看到是否有压栈:
bt即可,同理,也是有自己的编号的。
好了,该离开了,quit ,离开,简称q:
以上是关于gdb的一些浅薄的介绍,更详细的后续再更新。
感谢阅读!