gdb学习

1.GDB 的基本介绍

GDB, 是 The GNU Project Debugger 的缩写, 是 Linux 下功能全面的调试工具。GDB 支持断点、单步执行、打印变量、观察变量、查看寄存器、查看堆栈等调试手段。在 Linux 环境软件开发中,GDB 是主要的调试工具,用来调试 C 和 C++ 程序。

在终端输入以下命令安装 GDB:

1
$ sudo apt-get install gdb

1.GDB的进入和退出

首先用bugging.c作为实验例子。

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
#include<stdio.h>

int foo(int n)
{

int sum;
int i;

for (i=0; i<=n; i++)
{
sum = sum+i;
}

return sum;
}

int main(int argc, char** argv)
{
int result = 0;
int N = 100;

result = foo(N);

printf("1+2+3+...+%d= %d\n", N, result);

return 0;

}

如果要调试程序,需要在 gcc 编译可执行程序时加上 -g 参数,首先我们编译 bugging.c 程序,生成可执行文件:

1
$ gcc bugging.c -o bugging -g -m64

其中 -o 指定输出文件名, 虚拟机的环境是 64 位的操作系统,所以默认会编译为 64 位的程序,添加 -m64 选项可以编译为 64 位。

如果在你的环境里编译报错,请安装 libc6-dev-i386 后再次编译:

1
$ sudo apt-get install libc6-dev-i386

输入 gdb bugging 进入 gdb 调试 bugging 程序的界面:

1
$ gdb bugging

在 gdb 命令行界面,输入run 执行待调试程序:

1
$ (gdb) run

在 gdb 命令行界面,输入quit 退出 gdb:

1
$ (gdb) quit

2.GDB 命令行界面使用技巧

命令补全:

任何时候都可以使用 TAB 进行补全,如果只有一个待选选项则直接补全;否则会列出可选选项,继续键入命令,同时结合 TAB 即可快速输入命令。

部分 gdb 常用命令一览表:

命令 简写形式 说明
list l 查看源码
backtrace bt,where 打印函数栈信息
next n 执行下一行
step s 一次执行一行,遇到函数会进入
finish 运行到函数结束
continue c 继续运行
break b 设置断点
info breakpoints 显示断点信息
delete d 删除断点
print p 打印表达式的值
run r 启动程序
until u 执行到指定行
info i 显示信息
help h 帮助信息

查询用法:

在 gdb 命令行界面,输入 help command 可以查看命令的用法,command 是你想要查询的命令。

执行 Shell 命令:

在 gdb 命令行界面可以执行外部的 Shell 命令:

1
2
> $ (gdb)!shell 命令
>

>

例如查看当前目录的文件:

3.GDB 查看源码

list 命令用来显示源文件中的代码。

  • list 行号,显示某一行附近的代码:

  • list 函数名,显示某个函数附近的代码:

  • list 文件名 : 函数名,显示某一个文件某个函数附近的代码,用于多个源文件的情况。

4.GDB 断点

1.设置断点

break 命令用来设置断点。

  • break 行号,断点设置在该行开始处,注意:该行代码未被执行

  • break 文件名 : 行号,适用于有多个源文件的情况。
  • break 函数名,断点设置在该函数的开始处,断点所在行未被执行

  • break 文件名 : 函数名,适用于有多个源文件的情况。

2.查看断点信息

info breakpoints 命令用于显示当前断点信息。

其中每一项的信息:

  • Num 列代表断点编号,该编号可以作为 delete/enable/disable 等控制断点命令的参数
  • Type 列代表断点类型,一般为 breakpoint
  • Disp 列代表断点被命中后,该断点保留(keep)、删除(del)还是关闭(dis)
  • Enb 列代表该断点是 enable(y) 还是 disable(n)
  • Address 列代表该断点处虚拟内存的地址
  • What 列代表该断点在源文件中的信息

3.删除断点

delete 命令用于删除断点。

  • delete Num,删除指定断点,断点编号可通过 info breakpoints 获得:

  • delete,不带任何参数,默认删除所有断点:

4.关闭和启用断点

disable 命令和 enable 命令分别用于关闭和启用断点:

disable 命令用于关闭断点,有些断点可能暂时不需要但又不想删除,便可以 disable 该断点。

enable 命令用于启用断点。

  • disable Num,关闭指定断点,断点编号可通过 info breakpoints 获得:

  • disable,不带任何参数,默认关闭所有断点。

  • enable Num,启用指定断点,断点编号可通过 info breakpoints 获得。

  • enable,不带任何参数,默认启用所有断点。

disable 和 enable 命令影响的是 info breakpoints 的 Enb 列,表示该断点是启用还是关闭

5.断点启用的更多方式

enable 命令还可以用来设置断点被执行的次数,比如当断点设在循环中的时候,某断点可能多次被命中。

  • enable once Num,断点 hit 一次之后关闭该断点
  • enable delete Num,断点 hit 一次之后删除该断点

这两个命令影响的是 info breakpoints 的 Disp 列,表示该断点被命中之后的行为。

6. 断点调试的一些命令

  1. 打印变量

调试的过程中需要观察变量或者表达式的值,所以先介绍两个基本的显示变量值的命令:

  • info locals

    打印当前断点处所在函数的所有局部变量的值,不包括函数参数。

  • print 变量或表达式

    打印表达式的值,可显示当前函数的变量的值、全局变量的值等

    print/FMT 可以控制打印的格式,常见的有x(十六进制)、t(二进制)、c(显示为字符)等。

  1. 启动程序

run 命令用于启动待调试程序,并运行到断点处停下。

  • run

    不带任何参数,启动待调试程序,不传递参数。

  • run 参数

    有些程序需要跟参数,直接带上参数列表即可,会传递给 main 函数的 argc、argv 变量。

  1. 单步命令

next, step, finish, continue, until 用于控制整个调试过程中,程序执行的流程。

  • next

    next 单步执行,函数调用当做一条指令,不会进入被调用函数内部

    next N,表示单步执行N次

  • step

    step 单步执行,会进入到函数调用内部

    step N,表示单步执行N次

  • finish

    执行程序到当前函数结束

  • continue

    执行程序到下个断点

  • until

    until N,执行程序到源代码的某一行

7. 断点小结

断点是调试最基本的方法之一,这一节主要介绍了断点相关的知识。主要是几个断点相关的命令。

  • list
  • info breakpoints
  • break
  • delete
  • disableenable
  • enable onceenable delete
  • next, step, finish, continue, until
  • info localsprint

不熟悉命令的时候,记得在 gdb 命令行下键入 help info breakpoints 等命令,查询帮助文档。

0%