GDB 学习笔记
关于GDB调试工具的学习笔记,学会了纯命令行的调试操作,才能更好地理解例如VSCode提供的图形界面的调试功能等,GDB在WSL2 Ubuntu上进行操作。
调试信息
可执行程序可以被调试的前提就是编译时加上了调试信息,通常是debug模式下,加上-g选项。
如果强行调试一个没有调试信息的可执行程序,将不能看见程序中的函数名或变量名等,而只是内存地址,并且会显示一条警告
1 | (No debugging symbols found in <program>) |
加载程序
正常情况下可以通过调试器来加载程序
1 | gdb <program> |
也可以先启动gdb,然后加载可执行文件
1 | gdb |
加载的程序并不会直接执行,需要使用start或run命令来启动程序。
如果是需要调试一个生成core文件并异常终止的程序,可以加上core文件来恢复现场
1 | gdb <program> <core dump file> |
如果需要调试一个正在运行的程序,可以加上进程ID(一个整数),gdb将会自动以attach模式进行调试
1 | gdb <program> <PID> |
命令行参数
在程序启动之前可以查看和设置传入main函数的命令行参数args:
show args:查看当前采用的main函数命令行参数set args:设置main函数命令行参数
例如
1 | (gdb) set args 10 20 |
执行控制
关于程序执行的调控命令:
start:启动程序,在main函数入口处暂停run:运行(直到遇到断点或错误)continue:(假设在断点处暂停)继续执行(直到遇到断点或错误)next:单步逐行执行,如果有函数调用,不会进入调用函数体)step:单步向下执行,如果有函数调用,则会进入调用函数体finish:向上执行,直到跳出函数体
断点(break)
设置断点的命令有很多,可以基于行号,函数名,与当前位置偏移等
1 | (gdb) break <line> |
注意,如果函数体具有重载,则有多种选择,此时可以加上函数参数类型来指定具体的函数,否则gdb会提供候选函数的列表,需要输入编号来确认。
设置临时断点(断点在触发一次后自动失效)
1 | (gdb) tbreak ... |
设置条件断点(只有满足一定条件才会触发)
1 | (gdb) break ... if <condition> |
禁用断点(需要首先打印并找到断点的编号)
1 | (gdb) disable <breakpoint_id> |
启用断点(在禁用之后可以让断点重新生效)
1 | (gdb) enable <breakpoint_id> |
删除断点(需要首先打印并找到断点的编号)
1 | (gdb) delete <breakpoint_id> |
查看变量(print)
print可以查看指定表达式的值
1 | (gdb) print <expr> |
例如
1 | (gdb) print my_variable |
监视点(display)
监视点可以做到在每次程序暂停时,自动打印指定变量的值,可以避免重复调用print查看变量
1 | (gdb) display <expr> |
取消对指定变量的监视
1 | (gdb) undisplay <expr> |
取消所有的监视点
1 | (gdb) undisplay |
观察点(watchpoints)
除了断点可以用来暂停程序,我们还可以设置观察点来观察一个表达式(变量也是一种表达式)的值是否有了变化,如果发生变化则立刻暂停
设置普通观察点,当表达式的值发生变化时立刻暂停
1 | (gdb) watch <expr> |
设置读取观察点,当表达式被读时立刻暂停
1 | (gdb) rwatch <expr> |
设置读取观察点,当表达式被读或者被写时立刻暂停
1 | (gdb) awatch <expr> |
查看源码(list)
list可以查看当前位置附加的源代码,也可以加上行号或函数名等来显示指定位置的代码
1 | (gdb) list |
指定的行数或者函数入口会显示在正中,默认会显示当前位置前后各5行的源代码,也可以查看和修改显示的总行数
1 | (gdb) set listsize <num> |
查看信息(info)
info命令可以查看很多信息,包括断点/变量/监视点/观察点等。
查看所有断点或指定编号的断点
1 | (gdb) info break |
列出当前的所有局部变量
1 | (gdb) info locals |
列出当前的所有变量
1 | (gdb) info variables |
查看所有的监视点
1 | (gdb) info display |
列出当前所有的观察点
1 | (gdb) info watchpoints |
修改变量
在程序暂停时,可以修改指定变量的值
1 | (gdb) set var <my_variable> = <new_value> |
例如
1 | (gdb) set var x=4 |
TUI 界面
gdb 的 tui 相关命令提供了基于命令行的简单 TUI 支持,可以在上半屏幕显示源码/汇编等,在下半屏幕使用 gdb 命令行操作。在 TUI 模式下,上下键操作会移动 TUI 上显示的行位置。
可以使用快捷键ctrl+x+a开启和关闭GUI界面。
命令缩写
gdb的很多完整单词命令都可以等价替换为单个字母的缩写:
| 字母 | 完整命令与含义 |
|---|---|
| b | break(断点) |
| c | continue(继续执行) |
| s | step(单步执行,逐语句) |
| n | next(逐过程,跳过函数调用) |
| r | run(运行程序) |
| p | print(打印变量值) |
| d | delete(删除断点) |
| l | list(显示源代码) |
| i | info(显示信息) |
| q | quit(退出 GDB) |
退出
quit或exit可以退出gdb,如果有正在调试的程序,则会终止程序(需要确认终止)
1 | (gdb) quit |
