GDB是我们在C/C++编程中常用的debug工具,常用GDB命令如下表。
使用GDB之前,需要保证你的Makefile中的相关编译选项配置成 –g –O0
加了 –g编译选项才能使用GDB调试,-O0是要你关闭所有编译器优化,因为编译器优化可能会改变行数,甚至改变你的代码结构,不便于debug,并且dgb时会出现各种奇怪的问题。
如果是bazel build的可执行文件,需要 保证编译的是debug版本,一般可加 -c dbg 的选项来编译。
如果调试的程序 有输入参数,可以使用 gdb --args program_name program_para1 ….. 进入gdb;或者 gdb program_name后在gdb 界面使用 set args $argv1 $argv2 … 来添加参数。
GDB 官方文档 Top (Debugging with GDB)
不错的GDB 教程 GDB调试教程:1小时玩转Linux gdb命令
GDB 调试器支持在被调试程序中打 3 种断点,分别为普通断点(breakpoint)、观察断点(watch point)和捕捉断点(catch)。普通断点作用于程序中的某一行,当程序运行至此行时停止执行。观察断点作用于某一变量或表达式,当该变量(表达式)的值发生改变时,程序暂停。而捕捉断点的作用是,监控程序中某一事件的发生,例如程序发生某种异常时、某一动态库被加载时等等,一旦目标时间发生,则程序停止执行。
GDB命令 | 注释 |
gdb ./sim | 进入GDB调试,sim为可执行文件 |
set args $argv1 $argv2 | 设置main函数的参数,如果不带额外参数,就不用set,如果多个参数,中间用空格隔开 |
r | Run,执行程序,一般在找bug的时候,尤其是segment fault的时候,都是进入gdb后,先r一下,程序报错后,bt找到错误的大概位置 |
bt | Backtrace 显示当前函数调用的堆栈,在出现 段错误的时候非常有用 |
up /down | 向上或向下切换函数堆栈 |
n | Next, 单步执行 |
c | Continue,继续执行 |
s | Step,单步进入函数 |
b file_name : line_num | Breakpoint,加断点,file_name是要加断点的文件名,如xx.h 或xx.cpp,line_name就是行数了。 这是GDB的精髓命令,出现bug时,我们肯定要追踪一些信息,如某行代码是否被执行,某个参数是否正常等,这些都需要 断点来进行配合。顾名思义,就是在程序在执行到文件的line_num行时停住,这时候我们在配合使用bt / n / p等命令来查看程序是否按照我们的预期在执行。 |
b file_name : line_num if condition | 条件断点,如果在一个循环中加了断点,那么每循环一次就会断住一次;这时候,如果错误是执行很多次之后才出现的,或者是某个条件满足时才出现的,那么久可以使用条件断点。 设置后,只有在condition条件满足时才会停住 注意命令中, if 的前面和后面一定要加空格 |
watch *( type ) addr | Watchpoint,观察点。设置后,可以查看addr对应内存的内容被改写情况,一般在出现野指针,内存被无故改写情况下使用。 比如有一个指针 T_p* t_example,我们发现这个指针的内容被无故改写过,但不知道在哪被改写了,这是就用上watchpoint了 首先我们肯定要加断点 来停到这一行所在位置;然后用 p t_example 打印出变量在内存中的地址,如果不是指针,则可以p & 变量 来得到内存地址。 接着就是加观察点watch * (T_p * ) addr ; 最后就是c,继续执行。 当addr对应的内存内容被改写时,程序会自动停住,并且给出内容改写前后的值,及停住的位置,这个位置就是改写内容的地方了。 |
p 参数/表达式 | Print 打印变量的值,也可以加上&打印地址,还可以加上/x 设置打印成16进制格式(默认是十进制打印) 还可以加* 打印指针,还可以打印表达式的值 |
display参数/表达式 | 自动显示 打印,设置后每次程序停下来的时候自动打印参数或表达式的值 |
checkpoint | 保持程序当前时间点的状态,并可以在之后恢复当前状态,编号从0开始,新增一个checkpoint,编号加1。应用场景:当我们需要通过加断点,disable某些断点,再enable某些断点等等繁琐的步骤才能到达某段我们怀疑的程序执行时间和位置点时,为避免下次再经过这么多步骤到达这个时间和位置点,可以设置一个checkpoint,等下次还想从这个状态点开始找bug时,直接用restart就可以恢复到这个状态点。 |
restart checkpoint_id | 和checkpoint配合使用,从某个check 点 恢复 注意此处是观察点id,也就是1..2..3等等 不是checkpoint的PID |
info b | Information,显示当前已经设置了哪些断点 |
en id | Enable 断点、观察点 断点和观察点是统一编号的 |
dis id | Disable 断点、观察点,没有删除,只是暂时使其不生效,还可以用en来恢复 |
del id | Delete,直接删除,不能恢复了 |
catch / tcatch | 设置捕捉断点,比如 catch throw int ,如果代码中 有 throw 1之类的语句,就可以捕获到。 |
catch throw std::exception | 如果代码中 有 throw std::exception,那么在 gdb中 添加 catch throw std::exception 就可以定位到。 |
q | Quit,退出gdb |