【Linux】调试器-gdb
Linux下编译代码的默认模式
在Linux下我们使用gcc/g++编译代码,默认是release模式,release模式是无法调试的,
如果想让你的代码以debug形式发布,需要在gcc/g++后加上-g选项。
所以如果你没有在gcc/g++后面加上-g选项,使用gdb调试该程序,会出现下面这种情况
它会告诉你该程序没有调试信息,你是没有办法进行调试的。
而我们添加了-g选项编译生成的可执行程序是可以使用gdb进行调试的。
除了这种方法可以证明Linux下gcc/g++编译代码,默认是release模式以外,我没还可以看一下添加-g选项编译的可执行程序与没有添加-g选项的可执行程序的大小,代码以debug形式发布会比代码以release形式发布要大,因为以debug形式发布的可执行程序要加入一些调试信息。
在Linux中形成的可执行程序格式是elf格式。所以我们还以是使用readelf命令来获取可执行程序的二进制格式,所以我们就可以查看可执行程序是否有debug信息。
所以如果你想让你的程序被调试,gcc/g++时必须添加-g选项,以debug形式发布。
gdb的使用
如果想使用gdb调试程序直接在gdb后面加入你想调试的可执行程序名称即可,前提是你要调试的可执行程序在当前目录下。
gdb 可执行程序名称
如果想要退出gdb,输入quit即可退出
list选项,简称l
这个选项可以让我看见我们调试的代码,并且显示对应的行号。
但是它并不会从头开始为我们显示,所以我们可以在 lsit 或 l 后面加上数字,来从我们指定的行号打印。
gdb会记住我们上一次输入的选项,所以我们只要回车,即可查看后面的代码。
run选项,简称r
这个选项就是运行程序开始调试,遇到断点停止。
打断点
如果我们想要打断点,可以使用break选项,简称b
我们在 break 或 b 后面加上想打断点的行数即可完成。比如说我们想对第18行打断点,直接break/b 18。
这里还有一个问题,就是如果调试多个源文件怎么打断点,很简单,直接break/b + 源文件名称 + : +行号即可。
如果想对某个函数打断点,break/b + 函数名
如果想跨文件给函数打断点 break/b + 源文件名称 + :+ 函数名
查看断点
如果我们想要查看有哪些断点,输入info break/b选项即可查看。
删除断点
delete/d + 断点的序列号,断点的序列号就是info b 左边的Num
比如我们要删除一号断点直接 delete/d 1就是删除该断点。
这里要注意断点的序列号是递增的,比如我们删除了4号断点,再添加回来时,不会再重新生成4号断点而是会生成5号断点。
如果这我们使用quit退出gdb,再进入gdb,我们之前打的所有断点会清空。
断点的启用和禁用
disable:禁用断点
enable:启用断点
比如我们现在这个代码的第18行打一个断点。
我们查看断点时,Enb列表,表示这个断点是否被启用(y表示启用n表示禁用)。
我们可以看到1号断点时被启用的,这是我们run以下,这个程序会在第18行停止。
无论我们使用多少次run选项它始终会停在第18行。
这是使用disable把断点禁用,这个程序就不会停在第18行,使用info b查看断点时一号断点的Enb列表会从y变成n。
这个断点并没有被删除,只是被禁用了,如果这时使用enable将该断点启用,那么再使用run时又会停留在第18行。
逐过程运行
next/n
只用在run执行后才可以使用,所以我们需要打断点,比如所我们在第17行打一个断点,然后run一下,这时我们就可以使用next/n这个指令了。
这个指令它不会进入调用的函数里面,会直接跳过这个函数。
逐语句运行
step/s
它和next的区别就在于,它会进入调用的函数内部。
查看变量
p
p + 变量名,就可以查看变量的值
p + &变量名,就可以查看变量的地址
但是我们在进行调试的时候会发现,变量的值没法常显示,如果想要让变量在调试的时候常显示,就用用到display指令
display + 变量名
如果不想显示了undisplay + 序列号
跳转
until + 指定行数,会跳转到指定的行
finish
如果进入一个函数,想要将该函数执行完就停止,可以使用finish指令。
continue
简称c
如果想从一个断点直接运行到下一个断点可以使用continue指令
调用堆栈
bt,可以查看调用堆栈,函数的调用情况
修改变量的值
set var 变量名 = 修改的值
info locals
显示当前函数局部变量的值