前言
gdb是Linux下一款强大的程序调试工具,本文简要归纳了日常程序调测时频繁会使用的一些gdb指令。
启动调试
根据实际调试场景的不同,gdb支持多种方式启动调试,
对开发中的程序进行调试
shell # gdb ./a.out
对程序coredump文件进行调试
coredump文件可以使用gdb程序进行调试。gdb使用coredump文件启动调试示例如下:
shell # gdb -c coredump ./a.out
后续就是使用gdb去查找程序崩溃的原因了。
对运行中的程序进行调试
这种情况下,一般需要使用通过ps命令,获取到运行程序的进程ID,然后attach到该进程进行调试:
gdb -p pid
基本调试指令
程序运行
- run:运行当前程序
- continue: 恢复程序运行,直到程序结束或者遇到断点
- until:运行程序直到退出当前循环
- finish: 运行程序,直到当前函数完成,函数返回时打印出函数堆栈地址、参数值以及返回值等信息
- kill:终止当前运行的程序
单步调试
- next <count>: 单步跟踪,若未指定count值,默认执行单条语句,否则执行后续的count条语句。Next指令遇到函数调用时,不会进行该函数。
- step <count>:单步跟踪,若未指定count值,默认执行单条语句,否则执行后续的count条语句。Step指令遇到函数调用时,会进入该函数。
断点设置
- break <where>: 设置断点位置
- delete <breakpoint#>:删除断点
- enable <breakpoint#>:使能断点
- clear:删除所有断点
- disable <breakpoint$>:去使能断点
- info breakpoints:查看设置的断点信息
观察点设置
- watch <where>:被设置观察点的变量发生修改时,打印显示
- delete <watchpoint#>:删除观察点
- enable <watchpoint#>:使能观察点
- disable <watchpoint#>:去使能观察点
- info watch:显示观察点信息
函数调试
- frame <frame#>:切换到frame#(frame#为栈层次编号,可使用info frame进行查询)指定的层次的函数栈
- down:切换到下一层函数栈
- up:切换到上一层函数栈
运行时数据查看
查看函数栈信息
- backtrace <num>: 查看函数栈信息,可简写为bt。若num是正数,打印栈顶上num层的函数调用信息;若num是负数,只打印栈顶下num层的函数调用信息;默认打印当前所有函数调用栈的信息
- frame:打印出当前函数栈的层次编号、函数名、函数参数、函数所在文件和行号,以及函数执行到的语句
- info frame:打印出更为详细的当前函数栈的信息
- info args:打印出当前函数的参数以及对应的参数初始值
- info locals:打印出当前函数中所有局部变量以及对应的值
查看变量信息
- print <format> <expr>:使用指定的格式查看程序中的数据
print命令兼容C语言中访问变量的方式,如数组下标、解引用、数据类型转换等操作。
- display:追踪查看变量的值
- undisplay:取消追踪查看变量的值
查看寄存器数据
- info registers <regname>:查看当前运行过程中寄存器的信息,但不包括浮点寄存器;若指定了regname,则只查看指定寄存器的信息
- info all-register: 查看所有寄存器的信息,包括浮点寄存器
查看内存数据
- x/nfu :examine指令用于查看指定内存地址的值,简写为x。对指令后接的nfu作用描述如下:
- n: 待显示的内存单元个数
- f:显示格式
- u:每个内存单元的大小,按字节数来计算。默认是4 bytes.
支持的显示格式如下表:
格式符 | 描述 |
---|---|
x(hex) | 按十六进制格式显示变量 |
d(decimal) | 按十进制格式显示变量 |
u(unsigned decimal) | 按十进制格式显示无符号整型 |
o(octal) | 按八进制格式显示变量 |
t(binary) | 按二进制格式显示变量 |
a(address) | 按十六进制格式显示边领 |
c(char) | 按字符格式显示变量 |
f(float) | 按浮点数格式显示变量 |
查看源码
- list:查看当前上下文的源码
- list <filename>:<function>:查看指定函数的源码
- set listsize <count>:设置list查看的代码行数
- disassemble [<where>]:反汇编当前函数或指定位置
多线程调试
- info threads:显示当前可调试的所有线程,每个线程会有一个GDB为其分配的ID,后面操作线程的时候会用到这个ID。 前面有*的是当前调试的线程
- thread ID(1,2,3…):切换当前调试的线程为指定ID的线程
- set scheduler-locking on/off:设置on,只有当前被调试程序会执行;设置off不锁定任何线程,也就是所有线程都执行,这是默认值
退出调试
- quit