GDB
GDB 工具族
gdb 族有很多工具,经过我的测试,比较好用的有如下几个:
- gdb,这个基本很多环境都自带,肯定要学一下
- cgdb,和 gdb 基本差不多,但显示效果更好,有语法高亮
- gdbgui,显示效果非常好,使用 python flask 做个一个网页前端
- vscode 自带插件可以连接到远程 gdb 或使用 gdb attach 到指定进程
其他还有一些:
- ddd,这个我感觉不是很好用,但是有 gui,可以试试
- lldb,没有实际使用过,和 cgdb 类似,好像对 llvm 适配较高
本文主要使用 cgdb 和 gdb 进行讲解。
启动
启动前先说一下,需要使用 Debug 模式编译。
- 从可执行文件启动:
gdb --args <executable-file> <arg1> <arg2> <argn>
gdb <executable-file>
- 启动后,连接到正在运行的进程
- 基于进程号:
sudo gdb --pid <pid>
- 基于命令名称:
sudo gdb --pid ¥(pgrep -n <command name>)
- 基于进程号:
- 远程调试
- 启动远程调试服务:
sudo gdbserver --multi :9999 --attach <pid>
- 连接到远程调试服务:既然都用远程调试了,当然是为了使用 IDE 自带的功能连上
- 启动远程调试服务:
重要的 gdb 启动参数:
--tui
:和 cgdb 类似的代码展示窗口-x <file>
/-ex <command>
: 启动时执行命令
Best Practice
首先把常用命令先写到文件中
# debug_file.gdb
b some_namespace::SomeClass::some_func
c
n
p <var>
sudo cgdb -- --pid $(pgrep -n <command name>) -x debug_file.gdb
cgdb 使用 Esc
进入源码窗口,使用空格给当前行加断点,使用 i
回到 gdb 窗口。
常用命令
- 启动配置
set pagination off
:关闭启动提示set print elements 0
:显示...
的完整内容set listsize 30
:l
命令最大显示行数
- 进程 / 线程
i proc
:看进程、可知性文件情况i threads
:看线程,注意这里面的线程编号并不是操作系统的线程号p ¥_thread
:看断点所在线程thread <thread-id-by-gdb>
切换到某线程thread apply all <command>
:每个线程都运行某指令
- 函数运行状况
bt
/where
/bt full
:看堆栈调用层次bt 1
/bt -1
可以指定打印堆栈 traceback 的层次
p (rint)
:打印,不光能打印还能赋值;能直接打印整个对象的内容- 断点
- 增
b <file-name>:<line-number>
b <func>
b *<address>
b <func> thread <thread-id-by-gdb>
:可以使用thread
命令指定特定线程b <func> if <expression>
:可以使用if
命令加入条件断点
- 查
i breakpoints <breakpoint-number>-<breakpoint-number>
查看断点
- 删
d breakpoints <breakpoint-number>-<breakpoint-number>
删除断点,不加参数默认删掉所有
- 增
- 运行
l
显示当前位置,这个命令有 cgdb 后就不需要了n (ext)
:下一行ni
/si
:跳入函数finish
:跳出函数c (ontinue)
- 打印变量
p (rint) <expression>
:不光能直接打印变量 / 对象,还能计算表达式求值,可以调用函数 / 赋值,但调用函数一般用call
display
/undisplay
/i display
:自动打印变量,好像类似于 watchi args
:打印函数参数i locals
:打印局部变量
- 函数
call <function-name>
return <return-value>