GDB

GDB 调试器的使用

前提需求

  • 如果是使用 GCC 编译程序的时候,需要使用 -ggdb3 -Wall 参数

  • 如果是使用 CMake,则 CMAKE_BUILD_TYPE 需要设置为Debug/RelWithDebInfo

另外,调试时如果用到了动态库,gdb 会自动下载动态库的 debuginfo。对于 Fedora 而言,还可以使用 dnf debuginfo-install 手动安装。包名与提供动态库的包名相同

设置断点

gdb 通过 breakpoint 进行打断点,此指令的简写形式为 break、b。命令格式为

break location
break location if cond

其中 location 的值为:

location

含义

行号

入口函数所在文件的行号

文件名:行号

指定文件的行号

函数名

在函数内部的第一行代码暂停

文件名:函数名

在执行指定文件的指定函数时暂停

此外,上述所有 location 都可以接 location offset 的形式进行偏移。offset 可为正负,单位为行

命令

做用

d [n]

删除所有断点或者删除 n 号断点

clear [行号]

删除指定行断点

disable

禁用断点

enable

启用断点

info breakpoints

查看断点

运行代码

执行有两种方式:

命令

作用

run

直接运行到断点

start

在 main() 处中断

next

Step Over

step

Step Into

cont

执行到下一个断点

查看运行时信息

bt

显示栈帧

bt full

显示局部变量

print/p

计算并打印表达式的结果

display

跟踪表达式的结果

info reg

查看寄存器内容

watch

表达式变化时暂停

awatch

表达式 rw 时暂停

rwatch

表达式 r 时暂停

step

修改变量的值

多线程如何调试?

线程里直接加个 while(true) 等线程开始后 attach 进去,然后手动退出循环

GDB 脚本

将 gdb 调试过程写入一个文件中,就成为了一个 gdb 脚本。此脚本可在启动时通过参数 -x 引入,以自动完成某些工作。例如:

b threadpool.cpp:8
run
b if terminate_ == true
c

然后通过命令 gdb ./build/Debug/threadpool_test -x ./debug.gdb 启动命令即可

调试 Core 文件

首先拷贝并解压 Core 文件

cp cp /var/lib/systemd/coredump/core.test_threadpool.zst .
extract core.test_threadpool.zst

然后使用 gdb ./build/Debug/threadpool_test core.test_threadpool 开始调试。之后可以通过 bt 查看栈帧

跟踪过程调用

有三个相关工具:strace, ltrace 和 ftrace 分别用于跟踪系统调用、用户态程序调用和所有函数调用

多线程调试

多线程情况下崩溃有以下几种原因:

  • 对失效的锁(对象失效)调用了 lock

  • 加锁解锁顺序不对

  • 加锁解锁不在同一线程中

  • 对无锁的锁尝试解锁

动态库调试

动态库的调试与普通二进制文件的调试差不多,在加载可执行文件后,直接通过 breakpoint function_name 打断点,之后出现的提示选 y,正常执行即可