gdb的使用
使用gdb之前,首先要通过gcc的-g选项生成调试信息
$ gcc -g -Wall 源文件
启动:
$ gdb 可执行文件
设置断点:
break 断点
break可简写为b,断点可通过函数名、文件内的行号等来设置,如果不指定断点位置,就在下一行设置断点。
设好的断点可以通过 info break来确认
条件断点
break 断点 if 条件
条件可以为测试变量的值。
运行:
run 参数
参数为可执行文件需要的参数
start
效果等同在main设置断点,然后执行到main函数。
显示栈帧
backtrace 简写为bt
bt N 显示开头N个栈帧
bt -N 显示最后N个栈帧
bt full 不仅显示栈帧,还显示局部变量。
显示变量
print可以显示变量,简写为p
p 变量名
p/格式 变量名
常用格式 x(十六进制)、d(十进制)、u(无符号十进制)、o(八进制)、t(二进制)、a(地址)、c(字符)、f(浮点)、s(字符串)、i(显示机器语言 只在x命令中可用)
显示寄存器
在寄存器名之前加$即可显示其内容。
常用寄存器:$pc(也写为$eip ) 程序指针。
x命令:
格式为 x/NFU ADDR
N为重复次数
F为前面讲过的格式
U为单位:b(字节)、h(2字节)、w(4字节)、g(8字节)
例:
x/10i $pc 显示从pc所指地址开始的10条汇编指令。
单步执行
next(简写为n) 不会进入函数
step(简写为p) 执行到函数内部
继续执行
continue
程序会在遇到断点后再次暂停
continue 次数
指定次数可以忽略N次断点。
反复执行
ignore 编号 次数
在编号指定的断点、监视点或捕获点忽略指定的次数。
运行程序,直到当前函数完成返回,并打印函数返回时的堆栈地址和返回值及参数值等信息。
finish
运行程序直到退出循环体
until (简写为 u)
监视点
要找到变量在何处被改变,使用watch命令
watch 变量 改变时暂停运行
awatch 变量 被访问、改变时暂停运行
rwatch 变量 被访问暂停运行
删除监视点和断点
格式:delete <编号>
改变变量的值
set variable <变量>=<表达式>
attach到进程
要调试已经启动的进程或是陷入死循环无法返回的进程时,可以使用attach命令
attach pid
断点命令
commands 断点编号
命令
end
获取进程的内存转储
用ulimit命令查看当前的内核转储功能是否有效
ulimit -c
-c表示内核转储文件的大小限制。
开启内核转储:
ulimit -c [size]
size表示转储文件的大小,设为unlimited表示不限制大小。
一般转储文件会在当前目录下生成。
gdb调试转储文件:
gdb -c [core] [executable file]
可以看到程序错误原因和在第几行发生的错误
示例:
$ ./a.out
段错误 (核心已转储)
$ file core*
core: ELF 32-bit LSB core file Intel 80386, version 1 (SYSV), SVR4-style, from './a.out'
$ gdb -c core ./a.out
GNU gdb[...]
[New LWP 3586]
Core was generated by `./a.out'.
Program terminated with signal SIGSEGV, Segmentation fault.
#0 0x080483f5 in main () at 1.c:17
17 a->b = 2;
使用list命令可以查看附近源代码
(gdb) l
12 };
13
14 int main()
15 {
16 struct a *a = NULL;
17 a->b = 2;
18 return 0;
19 }