目录
在我们编写代码的过程当中我们肯定会遇到程序运行的结果不符合预期的情况,这个时候我们就需要通过调试代码找到错误,并进行修改。
在平时的程序编写的时候我们使用的都是VS2019集成开发软件,其中已经封装了图形化界面的调试方案。可以很好的帮助我们进行代码的调试。但是在Linux系统当中,我们要想对代码进行调试就需要使用我们的调试工具,并通过特定的指令进行代码的调试以及运行。
在本次的博客当中我们将对比在VS2019环境当中的代码调试步骤以及在Linux当中的代码调试步骤,帮助我们学习gdb代码调试工具。
gdb工具的使用
在使用gdb进行代码调试之前我们需要认识一下运行代码的两种形式:debug模式和release模式。这两个版本的代码的区别就在于debug模式允许我们对代码进行调试,但是release模式下不允许对代码进行调试。
因为release模式是针对于用户使用的。我们的用户只需要使用完好的软件,并不需要对软件进行调试寻找错误。因此为了减少我们软件所占的空间会减少一些内容,这一部分减少的内容就是我们debug文件当中所蕴含的调试信息。也正是因为有了这些调试信息我们的程序才可以允许我们进行调试。
在使用gdb对代码进行调试之前我们需要创建一个C语言文件。
将我们编写完成的代码通过gcc进行编译之后会生成我们的可执行程序,但是这个可执行程序是release版本的,并不是在所有的Linux平台当中都可以直接使用gdb进行调试。我们需要在编译的时候加上-g选项,生成一个debug版本的可执行程序。
通过观察可以看出debug版本下的可执行程序确实比release文件的体积要大,也符合添加了调试信息的原理。
之后就可以使用gdb对代码进行调试了。
其中for bug reporting instruction的含义是用于错误报告说明,表示我们已经成功进入了代码调试界面,接下来我们就来对比VS当中的调试功能进行学习Linux当中的代码调试指令。
代码调试相关指令
同样的我们在VS 当中也创建一个test.c文件。
运行程序指令 r
当我们想要运行我们的代码的时候,在VS2019当中我们可以按ctrl+F5组合键快速执行。
与之相对应的gdb当中我们直接输入r命令也可以得到相同的效果。
由于在Linux平台下面没有图形化界面所以会直接显示我们程序执行的结果,如上图所示。
显示代码的指令 l
由于在VS当中我们对一段代码进行调试的时候并不会关闭我们的代码,所以我们并没有显示代码的功能。但是在Linux当中这个功能就显得很必要了,有时候我们的代码比较长,那么就需要一边看着代码以便进行调试,这样才可以更好的进行调试功能。示例如下:
我们可以在 l 后面跟上我们想要显示代码的行号,这样就可以显示我们想要的目标代码。同时gdb具有记忆功能,我们在输入一次指令之后,就可以重复上一次输入的指令,不必再重复进行输入。因此我们只需要输入一次 l 0 之后直接按回车就会得到我们的全部代码。
给代码打断点 b
在对代码进行调试的时候,我们经常会用到给代码打断点的作用。这样可以快速让我们的代码跳转到指定的位置上。在VS2019当中也同样具有这样的功能,我们只需要在代码行左端的位置按左键点击一下,就会显示一个红点,这就是我们对代码打的断点。 例如我们在上面第8行的位置上打了一个断点。如果想要执行代码到断点的位置出停止,我们只需要点击F5就可以了。
当我们的界面跳转到这样就说明VS软件已经进入调试模式。
而在gdb当中我们要想给代码在一个特定的位置打一个断点需要使用 b 指令,b 代表着 break 我们可以通过 b + 行号 在指定行的位置上给代码打好断点。例如:
就像我们上图中所示的内容一样,输入指令之后就会显示我们在哪一个文件当中第几行打上了断点。
查看断点位置 info b
既然打上了断点万一忘记了应该怎么办呢?怎么查看我们在什么位置打了断点呢?在VS当中由于图形化界面的应用,我们只需要拖动我们的鼠标就可以看到我们打断点的位置。但是在Linux平台下面我们就需要继续输入指令了,这个时候就用到了info b指令,执行效果如下:
我们会发现我们上面依次打的三个断点,不仅可以查看而且他们已经被编号序号。
执行代码到断点处停止
在VS当中要想执行代码到断点的位置停止,我们只需要点击F5按键即可,要想跳转到下一个断点的位置我们只需要继续点击F5按键就可以实现。
但是gdb好像就没有这么方便了,我们第一次下个要执行代码到第一个断点的位置处停止,我们就需要输入 r 命令即可。
输入r命令之后我们的程序就会执行到我们第一个断点的位置处然后停止。如果继续输入 r 指令呢?
当我们第二次输入的命令之后,我们会发现我们的代码重新开始运行了。并没有按照我们的预期执行到我们的断点处停止。所以要是想要跳转到第二个断点的位置处停止,我们可以输入 c 指令。
我们会发现我们输入c指令之后断点数会逐步增加,也就对应着我们断点之间的跳转。
关闭断点 d+断点编号
学会添加并且跳转断点之后,下一步就需要进行断点的删除。在VS2019当中,删除一个断点只需要再次点击即可。
在gdb当中我们想要删除一个断点需要输入 d+断点编号的指令。例如:
我们先通过info b指令查看断点,之后通过d+断点编号的命令删除断点,最后通过info b命令进行查看,我们会发现我们的断点和我们的预期一样被删除了。
关闭某个断点,但不删除 disable+编号
当我们想要暂时屏蔽某个断点的时候在VS2019当中我们需要单击右键,然后选择禁用断点,当我们的断点颜色变白的时候我们这个断点就已经被禁用完毕了。我们再次按F5就会直接跳到下一个断点的位置处。
而在gdb当中想要完成这个功能我们需要输入disable+断点编号的命令来关闭一个断点。
我们只需要观察info b当中的信息,其中disp 就表示是否启用该断点,如果启用就表示为y,否则就表示为n。
打开某个断点 enable+断点编号
想要打开某个断点我们在VS当中需要执行重复的操作,右键单击禁用的断点之后点击启用断点即可达到目标效果。
而在gdb当中我么需要输入enable+断点编号的指令,打开某个关闭的断点。示例如下:
输入指定的指令之后就会发现我们禁用的指令已经打开了。
逐过程调试代码 n
常用的代码调试的方式其实是一步一步的调试,当我们的程序运行到大致的位置的时候,通常情况下我们会使用一步一步进行执行的方式得到调试的结果。逐过程调试也就是不进入我们的函数当中,将函数看作是一个整体,直接得到返回值。在VS当中就相当于我们的F10操作。点击之后,会运行到代码的下一步,但是不会进入函数当中。
我们会发现我们按F10之后程序没有进入函数当中直接跳到了下一行。
在gdb调试当中要想执行相应的步骤,我们需要输入 n 指令。发挥的是相同的作用。
在17行的位置打一个断点,之后运行代码,程序就运行到了第17行的位置。之后我们输入n指令,代码就跳到了第18行的位置,不进入函数。
逐语句调试代码 s
和逐过程调试代码相对应的就是逐语句调试代码,和逐过程最大的区别就在于逐语句调试代码最大的特点就在于会进入函数当中,我们可以看到函数当中的运行过程,方便我们进一步对代码进行调试操作。在VS2019当中我们只需要点击F11就可以执行逐语句调试代码的效果。例如:
在gdb当中逐语句调试代码需要输入 s 指令,所发挥的作用同样是进入到函数中进行调试等操作。例如:
我们会发现同样的操作,我们输入 s 会直接进入到函数内部,如果下一条指令不是函数就会正常的跳转到下一条代码的位置。
查看某个变量的值 p+想要查看的变量名
学会了调试的步骤之后我们会很好奇,但是我们还是不知道我们变量的值呀。在VS当中我们可以通过监视窗口观察我们想要查看的变量值。例如:
我们在右边输入的变量的值会随着程序的运行而变化,这也很好的帮助了我们检查代码到底是运行到了那一步出了问题。
在gdb当中我们要想查看某一个变量的值就需要输入 p+想要查看的变量名 这样就可以查看到指定的变量的值了。测试效果如下:
当我们输入指令查看sum变量的值的时候,我们会发现刚开始sum的值为0,但是随着我们程序的执行再次查看变量的值就变成了6。
常显示变量的值 display+想要查看的变量名
但是我们会发现gdb当中的查看变量的值的使用方式并不方便,我们每一次都得重新输入一次p指令才可以得到想要的结果。所以为了解决我们上面所出现的问题,就有了常显示变量的值,我们就需要输入display+想要查看的变量名的指令进行查看。测试效果如下:
我们会发现,当我们输入指令之后在下方就会自动输出一个sum变量,并且这个变量会随着我们程序的执行而改变。
关闭常显示 undisplay+对应的编号
当我们不想使用常显示的时候我们需要输入undisplay+该变量对应的编号的指令进行取消常显示。对应的编号也就是我们为常显示变量分配的编号。就比如图中sum的编号就为1。测试指令的运行效果如下:
输入玩相应的指令之后,我们会发现我们的sum常显示也就被取消了。
那么此上就是gdb当中最常用到的关于调试的相关指令了,我们平时需要多多练习,等熟练了之后我们可以将目光转向更为方便的具有图形化界面的调试工具。