📜  GDB-调试示例(1)

📅  最后修改于: 2023-12-03 15:30:53.112000             🧑  作者: Mango

GDB-调试示例

GDB是一个功能强大的调试工具,可以帮助程序员识别和修复程序中的错误。在本文中,我们将介绍GDB的用法和一些常见的调试示例。

GDB的基本用法

GDB可以在命令行界面中使用。启动GDB后,可以使用以下命令进行常见操作:

  • run:运行程序,如果需要输入参数可以在后面添加。
  • break:在代码中设置断点,以便在特定位置停止。
  • step:逐行执行程序。
  • next:逐行执行程序,但不进入函数。
  • print:打印变量的值。
  • continue:继续执行程序直到下一个断点或程序结束。
  • quit:退出GDB。
调试示例
示例一:程序崩溃

下面是一个导致程序崩溃的简单C程序:

#include <stdio.h>
#include <stdlib.h>

int main() {
    char *ptr = NULL;
    printf("%c", *ptr);
    return 0;
}

该程序中没有对指针进行初始化,因此在尝试访问ptr指向的内存位置时会导致崩溃。

使用GDB来查找此错误。首先,要编译程序时需要添加-g选项来生成可调试的二进制文件:

gcc -g example.c -o example

然后,使用GDB启动程序:

gdb example

使用run命令运行程序。当程序崩溃时,GDB会停止并显示一个错误消息。使用backtrace命令查看堆栈跟踪:

(gdb) run
Starting program: /path/to/example 
Program received signal SIGSEGV, Segmentation fault.
0x00005555555546c2 in main () at example.c:6
6       printf("%c", *ptr);
(gdb) backtrace
#0  0x00005555555546c2 in main () at example.c:6

这里显示了崩溃发生在main函数的第6行。使用print命令查看指针变量ptr的值:

(gdb) print ptr
$1 = 0x0

由于ptr的值为0x0,因此尝试访问该地址中的内容会导致崩溃。修复这个问题,只需要在使用指针之前将其初始化即可。

示例二:无限循环

这是一个无限循环的C程序:

#include <stdio.h>

int main() {
    int i = 0;
    while (i < 10) {
        printf("i = %d\n", i);
    }
    return 0;
}

由于i的值始终小于10,循环永远不会结束。使用GDB来查找这个问题。

首先,按上述方式编译并运行程序。程序将永远不会停止。使用Ctrl + C组合键停止程序,并使用backtrace命令查看程序停止时的堆栈:

(gdb) backtrace
#0  0x00005555555546c2 in main () at example.c:6

这里,GDB告诉我们程序停在了main函数的第6行,也就是循环的开始。使用next命令单步执行程序,看看何时停止:

(gdb) next
i = 0
7           printf("i = %d\n", i);
(gdb) next
i = 0
7           printf("i = %d\n", i);
(gdb) next
i = 0
7           printf("i = %d\n", i);

可以看到,程序无限循环打印相同的值。使用print命令查看i的值:

(gdb) print i
$1 = 0

由于i的值没有变化,因此循环永远不会结束。将循环条件更改为i <= 10,然后重新编译并运行程序即可解决此问题。