######################################## GDB ######################################## .. seealso:: - `100个gdb小技巧 `_ - `多线程中如何使用gdb精确定位死锁问题 `_ GDB 调试器的使用 前提需求 **************************************** - 如果是使用 GCC 编译程序的时候,需要使用 *-ggdb3 -Wall* 参数 - 如果是使用 CMake,则 CMAKE_BUILD_TYPE 需要设置为Debug/RelWithDebInfo 另外,调试时如果用到了动态库,gdb 会自动下载动态库的 debuginfo。对于 Fedora 而言,还可以使用 :command:`dnf debuginfo-install` 手动安装。包名与提供动态库的包名相同 设置断点 **************************************** gdb 通过 breakpoint 进行打断点,此指令的简写形式为 break、b。命令格式为 :: break location break location if cond 其中 location 的值为: +---------------+--------------------------------+ | location | 含义 | +===============+================================+ | 行号 | 入口函数所在文件的行号 | +---------------+--------------------------------+ | 文件名:行号 | 指定文件的行号 | +---------------+--------------------------------+ | 函数名 | 在函数内部的第一行代码暂停 | +---------------+--------------------------------+ | 文件名:函数名 | 在执行指定文件的指定函数时暂停 | +---------------+--------------------------------+ 此外,上述所有 location 都可以接 :command:`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 进去,然后手动退出循环 .. seealso:: - `调试器GDB的基本使用方法 `_ - `用gcc编译gdb调试 `_ - `GDB查看C++对象布局 `_ - `Linux下core文件调试方法 `_ - `你还在用GDB调试程序吗? `_ - `GDB常用命令与技巧(超好用的图形化gdbgui) `_ - `Using Bochs and the remote GDB stub `_ - `gdb查看函数调用栈_Hello,World-CSDN博客_gdb 调用栈 `_ - `[Linux] gdb 单步执行和跟踪函数调用_shiawaseli的博客-CSDN博客_gdb单步跟踪 `_ GDB 脚本 **************************************** 将 gdb 调试过程写入一个文件中,就成为了一个 gdb 脚本。此脚本可在启动时通过参数 -x 引入,以自动完成某些工作。例如: .. code-block:: none b threadpool.cpp:8 run b if terminate_ == true c 然后通过命令 :command:`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 然后使用 :command:`gdb ./build/Debug/threadpool_test core.test_threadpool` 开始调试。之后可以通过 bt 查看栈帧 跟踪过程调用 **************************************** 有三个相关工具:strace, ltrace 和 ftrace 分别用于跟踪系统调用、用户态程序调用和所有函数调用 多线程调试 **************************************** 多线程情况下崩溃有以下几种原因: - 对失效的锁(对象失效)调用了 lock - 加锁解锁顺序不对 - 加锁解锁不在同一线程中 - 对无锁的锁尝试解锁 动态库调试 **************************************** 动态库的调试与普通二进制文件的调试差不多,在加载可执行文件后,直接通过 breakpoint function_name 打断点,之后出现的提示选 y,正常执行即可