前言
之前在GDB的极致运用一文中,我们讲到了GDB启动调试的多种方式,分别应用于多种场景。今天我们来介绍一下断点设置的多种方式。
1.为何要设置断点
在介绍之前,我们首先需要了解,为什么需要设置断点。我们在指定位置设置断点之后,程序运行到该位置将会“暂停”,这个时候我们就可以对程序进行更多的操作,比如查看变量内容,堆栈情况等等,以帮助我们调试程序。
2.查看已设置的断点
在学习断点设置之前,我们可以使用info breakpoints查看已设置断点:
它将会列出所有已设置的断点,每一个断点都有一个标号,用来代表这个断点。例如,第2个断点设置是一个观察点,并且会忽略三次。
3.断点设置
断点设置有多种方式,分别应用于不同的场景。借助示例程序进行一一介绍:
编译:
注意,编译时需要带上-g参数,具体原因参见GDB的极致运用
(1)根据行号设置断点
或者
程序运行到第9行的时候会断住。
(2)根据函数名设置断点
同样可以将断点设置在函数处:
程序在调用到printNum函数的时候会断住。
(3)根据条件设置断点
假设程序某处发生崩溃,而崩溃的原因怀疑是某个地方出现了非期望的值,那么你就可以在这里断点观察,当出现该非法值时,程序断住。这个时候我们可以借助gdb来设置条件断点,例如:
当在b等于0时,程序将会在第23行断住。
它和condition有着类似的作用,假设上面的断点号为1,那么:
会使得b等于0时,产生断点1。而实际上可以很方便地用来改变断点产生的条件,例如,之前设置b==0时产生该断点,那么使用condition可以修改断点产生的条件。
(4)根据规则设置断点
例如需要对所有调用printNum函数都设置断点,可以使用下面的方式:
所有以printNum开头的函数都设置了断点。而下面是对所有函数设置断点:
(5)设置临时断点
假设某处的断点只想生效一次,那么可以设置临时断点,这样断点后面就不复存在了:
(6)跳过多次设置断点
假如有某个地方,我们知道可能出错,但是前面30次都没有问题,虽然在该处设置了断点,但是想跳过前面30次,可以使用下面的方式:
其中,1是你要忽略的断点号,可以通过前面的方式查找到,30是需要跳过的次数。这样设置之后,会跳过前面30次。再次通过info breakpoints可以看到:
(7)根据表达式值变化产生断点
有时候我们需要观察某个值或表达式,知道它什么时候发生变化了,这个时候我们可以借助watch命令。例如:
这个时候,让程序继续运行,如果a的值发生变化,则会打印相关内容,如:
但是这里要特别注意的是,程序必须运行起来,否则会出现:
因为程序没有运行,当前上下文也就没有相关变量信息。
rwatch和awatch同样可以设置观察点,前者是当变量值被读时断住,后者是被读或者被改写时断住。
4.禁用或启动断点
有些断点暂时不想使用,但又不想删除,可以暂时禁用或启用。例如:
5.断点清除
断点清除主要用到clear和delete命令。常见使用如下:
总结
本文介绍了常见的断点设置方法,断点设置之后,可以便于我们后期观察变量,堆栈等信息,为进一步的定位与调试做准备。
===========我是华丽的分割线===========