GDB调试工具使用说明
1. gdb 常规命令
命令 简写形式 说明
backtrace bt、where 显示backtrace
break b 设置断点
continue c、cont 继续执行
delete d 删除断点
finish 运行到函数结束
info breakpoints 显示断点信息
next n 执行下一行
print p 显示表达式
run r 运行程序
step s 一次执行一行,包括函数内部
x 显示内存内容
until u 执行到指定行
其他命令
directory dir 插入目录
disable dis 禁用断点
down do 在当前调用的栈帧中选择要显示的栈帧
edit e 编辑文件或者函数
frame f 选择要显示的栈帧
forward-search fo 向前搜索
generate-core-file gcore 生成内核转存储
help h 显示帮助一览
info i 显示信息
list l 显示函数或行
nexti ni 执行下一行(以汇编代码为单位)
print-object po 显示目标信息
sharelibrary share 加载共享的符号
stepi si 执行下一行
2. core dump 的使用
在 Linux 操作系统中,当程序执行发生异常崩溃时,系统可以将发生崩溃时的内存数据、调用堆栈情况等信息自动记录下载,并存储到一个文件中,该文件通常称为 core 文件,Linux 系统所具备的这种功能又称为核心转储(core dump)。幸运的是,GDB 对 core 文件的分析和调试提供有非常强大的功能支持,当程序发生异常崩溃时,通过 GDB 调试产生的 core 文件,往往可以更快速的解决问题。
- 无序列表查看是否开启 core dump 这一功能
ulimit -a
[root@]# ulimit -a
core file size (blocks, -c) 0
data seg size (kbytes, -d) unlimited
scheduling priority (-e) 0
file size (blocks, -f) unlimited
pending signals (-i) 7284
max locked memory (kbytes, -l) 64
max memory size (kbytes, -m) unlimited
open files (-n) 65535
pipe size (512 bytes, -p) 8
POSIX message queues (bytes, -q) 819200
real-time priority (-r) 0
stack size (kbytes, -s) 8192
cpu time (seconds, -t) unlimited
max user processes (-u) 7284
virtual memory (kbytes, -v) unlimited
file locks (-x) unlimited
如果 core file size(core 文件大小)对应的值为 0,表示当前系统未开启 core dump 功能
-
开启 core dump
ulimit -c unlimited -
调试 core 文件也很简单
$ gdb 程序文件名 core 文件名
3. 调试并运行程序
程序还未启动时,可有多种方式启动调试。
调试启动无参程序
例如:
$ gdb helloWorld
(gdb)
输入run命令,即可运行程序
调试启动带参程序
假设有以下程序,启动时需要带参数:
#include<stdio.h>
int main(int argc,char *argv[])
{
if(1 >= argc)
{
printf("usage:hello name\n");
return 0;
}
printf("Hello World %s!\n",argv[1]);
return 0 ;
}
编译:
$ gcc -g -o hello hello.c
这种情况如何启动调试呢?需要设置参数:
$ gdb hello
(gdb)run INONE
Starting program: /home/shouwang/workspaces/c/hello INONE
Hello World INONE!
[Inferior 1 (process 20084) exited normally]
(gdb)
只需要 run 的时候带上参数即可。
或者使用 set args,然后在用 run 启动:
$ gdb hello
(gdb) set args INONE
(gdb) run
Starting program: /home/hyb/workspaces/c/hello INONE
Hello World INONE!
[Inferior 1 (process 20201) exited normally]
(gdb)
4. 调试已运行程序
如果程序已经运行了怎么办呢?
首先使用 ps 命令找到进程 id:
$ ps -ef|grep 进程名
或者:
$ pidof 进程名
attach 方式
假设获取到进程 id 为 20829,则可用下面的方式调试进程:
$ gdb
(gdb) attach 20829
接下来就可以继续你的调试啦。
可能会有下面的错误提示:
Could not attach to process. If your uid matches the uid of the target
process, check the setting of /proc/sys/kernel/yama/ptrace_scope, or try
again as the root user. For more details, see /etc/sysctl.d/10-ptrace.conf
ptrace: Operation not permitted.
解决方法,切换到 root 用户:
将/etc/sysctl.d/10-ptrace.conf 中的
kernel.yama.ptrace_scope = 1
修改为
kernel.yama.ptrace_scope = 0
直接调试相关 id 进程
还可以是用这样的方式 gdb program pid,例如:
gdb hello 20829
或者:
gdb hello --pid 20829
已运行程序没有调试信息
为了节省磁盘空间,已经运行的程序通常没有调试信息。但如果又不能停止当前程序重新启动调试,那怎么办呢?还有办法,那就是同样的代码,再编译出一个带调试信息的版本。然后使用和前面提到的方式操作。对于 attach 方式,在 attach 之前,使用 file 命令即可:
$ gdb
(gdb) file hello
Reading symbols from hello...done.
(gdb)attach 20829
5. 查看/修改变量的值
在程序命中断点时,可以查看变量的值。这个变量可以是全局变量,也可以是局部变量,而且当前上下文能够访问的变量都可以查看。语法如下:
打印变量
p a
打印指针
p p
打印 main 函数中的变量 a
p 'main'::a
打印指针指向的内容,@后面跟的是打印的长度
p *p@3
如果要修改查看到的变量值,可以使用下述命令:
print 变量名=值
即如果要改变 x 变量的值,将它修改为 20,可以使用命令 p x=20 。对于结构体或者类对象,也可以使用这种方式修改成员的值,例如 p test->x=30 、p node.ID=100 等。