victor
发布于

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 等。

浏览 (352) 点赞 收藏 分享
评论