Skip to content
On this page

C语言调试工具GDB


标签:clang/kit  

以下内容摘自官网 GDB:GNU 工程调试器 (sourceware.org)


什么是GDB?

GDB,GNU工程调试器,允许你看到发生了什么在另一个程序执行时“内部”它 - 或者另一个程序 在它崩溃的那一刻正在做。

GDB 可以做四种主要的事情(加上支持中的其他事情 其中)帮助您捕获行为中的错误:

  • 启动程序,指定可能影响其行为的任何内容。
  • 使程序在指定条件下停止。
  • 检查程序停止时发生的情况。
  • 更改程序中的内容,以便您可以试验 纠正一个错误的影响,并继续了解另一个错误。

这些程序可能与 GDB(本机)在同一台计算机上执行, 在另一台计算机(远程)或模拟器上。GDB 可以在大多数上运行 流行的UNIX和Microsoft Windows变体,以及Mac OS X。

GDB 支持的语言 ?

  • Ada
  • Assembly
  • C
  • C++
  • D
  • Fortran
  • Go
  • Objective-C
  • OpenCL
  • Modula-2
  • Pascal
  • Rust

安装GDB

bash
# ubuntu
$ sudo apt install gdb
# check
$ gdb --version
GNU gdb (Ubuntu 12.1-0ubuntu1~22.04) 12.1
Copyright (C) 2022 Free Software Foundation, Inc.
License GPLv3+: GNU GPL version 3 or later <http://gnu.org/licenses/gpl.html>
This is free software: you are free to change and redistribute it.
There is NO WARRANTY, to the extent permitted by law.

QuickStart

c
#include <stdio.h>

int main()
{
    int arr[4] = {1,2,3,4};
    int i = 0;
    for(i = 0; i < 4; i++) {
        printf("%d\n", arr[i]);
    }
    return 0;
}

编译 :

bash
gcc -g test.c

生成的文件也是 a.out , 但可以通过 gdb 执行 :

bash
$ gdb a.out
GNU gdb (Ubuntu 12.1-0ubuntu1~22.04) 12.1
Copyright (C) 2022 Free Software Foundation, Inc.

For help, type "help".
Type "apropos word" to search for commands related to "word"...
Reading symbols from a.out...
(gdb)

可以看到 prompt 变成了 (gbd) , 先运行下 run 吧 ( 可以缩写成 r) :

bash
(gdb) run
Starting program: /home/ubuntu/ccc/a.out
[Thread debugging using libthread_db enabled]
Using host libthread_db library "/lib/x86_64-linux-gnu/libthread_db.so.1".
1
2
3
4
[Inferior 1 (process 267601) exited normally]
(gdb)

程序直接执行完了, 输入 quit 退出.

指令

常用的几个 GDB 指令可以通过 man gbd 进行查看:

break [file:][function|line]
           Set a breakpoint at function or line (in file).

run [arglist]
   Start your program (with arglist, if specified).

bt  Backtrace: display the program stack.

print expr
   Display the value of an expression.

c   Continue running your program (after stopping, e.g. at a breakpoint).

next
   Execute next program line (after stopping); step over any function calls
   in the line.

edit [file:]function
   look at the program line where it is presently stopped.

list [file:]function
   type the text of the program in the vicinity of where it is presently
   stopped.

step
   Execute next program line (after stopping); step into any function calls
   in the line.

help [name]
   Show information about GDB command name, or general information about
   using GDB.

quit
exit
   Exit from GDB.

break

打断点, 后面可以跟函数名和行数

bash
(gdb) b 9
Breakpoint 1 at 0x11b0: file testgdb.c, line 9.
(gdb) b main
Breakpoint 2 at 0x1175: file testgdb.c, line 4.

此时, 运行 r, 程序会在 main 暂停

bash
(gdb) r
Starting program: /home/ubuntu/ccc/a.out
[Thread debugging using libthread_db enabled]
Using host libthread_db library "/lib/x86_64-linux-gnu/libthread_db.so.1".

Breakpoint 2, main () at testgdb.c:4
4       {

next

如果想要继续执行, 输入 next :

bash
(gdb) n
5           int arr[4] = {1,2,3,4};

程序向下执行了 1 行

info

要查看已经打的断点:

bash
(gdb) info b
Num     Type           Disp Enb Address            What
1       breakpoint     keep y   0x00000000000011b0 in main at testgdb.c:9
2       breakpoint     keep y   0x0000000000001175 in main at testgdb.c:4

当然, info 支持查看其他内容

list

查看源代码, 方便断点:

bash
(gdb) list
1       #include <stdio.h>
2
3       int main()
4       {
5           int arr[4] = {1,2,3,4};
6           int i = 0;
7           for(i = 0; i < 4; i++)
8           {
9               printf("%d\n", arr[i]);
10          }

print

断点的主要目的就是在断点处查看变量的值, 用 print 指令:

bash
(gdb) p arr[1]
$1 = 2

step

进入当前行的函数调试, 一般是直接返回了

shell

在 GDB 中, 可以直接调用终端的指令:

bash
(gdb) shell ls
a.out  testgdb.c

watch

观察地址内容的变化, 变量内部的变化

bash
(gdb) print &i
$2 = (int *) 0x7fffffffe1fc
(gdb) watch *0x7fffffffe1fc
Hardware watchpoint 2: *0x7fffffffe1fc
(gdb) info watchpoint
Num     Type           Disp Enb Address            What
2       hw watchpoint  keep y                      *0x7fffffffe1fc
(gdb) n

Hardware watchpoint 2: *0x7fffffffe1fc

Old value = 0
New value = 1
0x00005555555551d3 in main () at testgdb.c:7
7           for(i = 0; i < 4; i++)

当程序不断执行下去的时候, 只要 watchpoint 的内容变化了, 会直接打印 old/new value.

开启日志

记录调试的过程

bash
(gbd) set logging on
Copying output to gdb.txt

调试错误退出 Core 文件

如下代码:

c
#include <stdio.h>

int main()
{
    int *tmp = NULL;
    *tmp = 10;
    return 0;
}

编译 & 运行:

bash
$ gcc -g test.c
$ ./a.out
Segmentation fault (core dumped)

产生段错误, 并生成 core 文件 : ( 无法生成 Core 文件: Core dumped, but core file is not in the current directory? )

bash
$ ls
ubuntu@ubuntu:~/ccc$ ls
a.out  core.269685  test.c

用 GDB 查看错误在什么地方 :

bash
$ gbd a.out core.269685
GNU gdb (Ubuntu 12.1-0ubuntu1~22.04) 12.1
Copyright (C) 2022 Free Software Foundation, Inc.

For help, type "help".
Type "apropos word" to search for commands related to "word"...
Reading symbols from a.out...
[New LWP 269685]
[Thread debugging using libthread_db enabled]
Using host libthread_db library "/lib/x86_64-linux-gnu/libthread_db.so.1".
Core was generated by `./a.out'.
Program terminated with signal SIGSEGV, Segmentation fault.
#0  0x000055bcffe0013d in main () at err.c:6
6           *tmp = 10;

可以看到是代码第六行出现了错误.

调试正在运行的程序

Last updated: