https://sourceware.org/gdb/documentation/
参考资料
- gcc/g++常用编译选项和gdb常用调试命令
- 使用gdb调试程序完全教程
- https://wizardforcel.gitbooks.io/100-gdb-tips/content/set-scheduler-locking-on.html
- https://www.cnblogs.com/euphie/p/9781482.html
- https://markrepo.github.io/tools/2018/06/22/gdb/
- https://blog.csdn.net/zhangye3017/article/details/80382496
gdb调试
- 生成可执行文件时,必须加入-g或-ggdb,使得可执行文件可调试。其中-ggdb信息更丰富,但只能用于gdb调试,不能用于其他调试器。默认为g2级别,可选g1级别(没有局部变量)、g3级别(包括宏)。
- gdb调试:
- gdb xxx.exe进入程序调试。或ps获取正在运行进程PID后,gdb PID挂载到PID进程上。(gdb以后 attach pid, b, c)
- l或list查看程序,一次显示10行,回车显示后10行。l func查看func函数,l 5,19查看5-19行。
- info program查看程序当前状态、暂停位置等。
- 断点:
- b或break添加断点。
- b 行号。
- b 函数名
- b 文件名:行号
- b 行号 if 条件
- info break查看所有断点。disable num禁用第num号断点,info break中的Enb字段会变为n。同理,enable num解禁第num号断点,delete num删除第num号断点。
- ignore 4 23忽略4号断点23次。
- b或break添加断点。
- 运行:
- r或run运行程序,和ide逻辑一样,再输入r回重新执行(不推荐)。c或continue继续运行。
- r --batch_interval 10 --debug_mode yes < ../output.xdis_preonline 参数和输入例子
- start程序运行到main定义变量后的第一行。
- n或next单步执行但不进入函数。
- s或step单步执行且进入函数,finish运行到跳出函数,return强行直接跳出函数。
- r或run运行程序,和ide逻辑一样,再输入r回重新执行(不推荐)。c或continue继续运行。
- 查看变量:
- p var或print var查看变量var的值。
- display var可以在每此前进后打印var的值,undisplay var取消每次输出var,info display查看display列表。
- watch var将var加入watch列表,当变量变化时会输出,通过info watch查看所有watch列表中变量的值和名称,disable、enable、delete对watch列表同样适用。
- 查看调用栈:
- bt查看当前栈帧和调用栈的情况。frame num查看调用栈第num层信息。
- up查看更浅层信息,down查看更深层信息,down 2向深走2层。
- 设置变量set var=54,将变量var设置为54。
- make在gdb中重新执行make文件。
- q或quit退出gdb。
gdb调试多线程文件
- info threads查看所有线程。
- thread id切换到第id个线程。
gdb调试core文件
- 程序崩溃时,会生成core文件,包含了崩溃时的内存映像和调试信息。生成core文件的过程叫core dump。
- gdb filename COREFILE会调试core文件,即程序崩溃前的内存映像。使用bt查看报错位置。
Type info variables
to list "All global and static variable names".
Type info locals
to list "Local variables of current stack frame" (names and values), including static variables in that function.
Type info args
to list "Arguments of the current stack frame" (names and values).
把值打印出来
(gdb) p *(item.second._M_dataplus._M_p)
$50 = 3 ‘\003‘
打印protobuf message
> p <var>.DebugString() # 使用DebugString()将proto对象内部结构打印出来
打印内存地址
# n:为正整数,表示需要打印的内存单元个数 # # f:打印格式, 如下 # - x: 十六进制 # - d: 十进制 # - u: 十六进制 # - o: 八进制 # - t: 二进制 # - a: 十六进制 # - c: 字符格式 # - f: 浮点数 # # u: 内存单元大小,如下: # - b: 单字节 # - h: 双字节 # - w: 四字节 # - g: 八字节 # > x/<n/f/u> <addr> # addr: 要打印的内存地址
打印长字符串
gdb会限制打印字符串的最大长度。使用下列命令可修改限制。
> show print elements # 显示字符串最大打印长度 > set print elements 0 # 取消字符串最大打印长度,可以打印长string的全部内容
线程调试
pstack <pid> # 可事先dump某个进程下所有线程的thread id和backtrace,方便gdb调试 > info threads # 查看当前所有线程信息 > bt # 查看当前线程的backtrace > bt full # 查看当前线程更详细的backtrace(每个栈帧上的参数) > thread <thread-id> # 切换到某一个线程 > set scheduler-locking on # 多线程环境下,只有当前被调试线程会执行 > set scheduler-locking off # 多线程环境下,除当前被调试线程之外的其他线程也在同步执行 > set scheduler-locking step # 多线程环境下,对当前被调试线程用step调试时,其他线程不会执行;使用next调试时,其他线程也许会执行
运行控制
> r arg1 arg2 ... # 重新开始运行二进制,如果需要传入参数内需要arg1 arg2... > stop # 暂停运行 > c # 继续执行(continue) > n # 单步执行(next),遇到函数则跳过 > s # 单步执行(step),遇到函数则跳入函数体 > finish # 运行直到跳出当前函数 > until line # 运行直到到达指定行 > call command # 运行C++命令 > shell # 进入shell模式,回到linux终端 > exit # 退出shell模式,回到gdb命令行 > set $var=XXX # 设置gdb变量 > set var=XXX # 设置程序中变量
starti 从第一条指令开始执行程序
layout asm 查看汇编
info register 查看寄存器
//查看当前运行的进程 ps aux|grep a.out
//查看当前运行的轻量级进程 ps -aL|grep a.out
//查看主线程和新线程的关系 pstree -p 主线程id
//查看栈结构 pstack 线程ID
gdb线程
//1.查看进程:info inferiors
//2.查看线程:info threads
//3.查看线程栈结构:bt
//4.切换线程:thread n(n代表第几个线程)
只运行当前线程
1. 设置:set scheduler-locking on
2. 运行:n
所有线程并发执行
1. 设置:set scheduler-locking off
2. 运行:n