Ch3nyang's blog

home

home

person

about

hive

project

collections_bookmark

mindclip

rss_feed

rss

GDB touturial: a walkthrough with examples

calendar_month 2020-08
archive 工具
tag gdb tag debug

本文参考自umd。可以配合online manual学习。

gdb 是个啥?

  • “GNU Debugger”
  • 众多语言的 debugger,包括 C 和 C++
  • 能展示程序运行时,在某个特定的地方程序干了什么
  • 使用 gdb 更容易发现诸如 segmentation faults 这样的错误

编译

通常我们这样编译程序:

gcc [flags] <source files> -o <output file>

例如:

gcc -Wall -Werror -ansi -pedantic-errors prog1.c -o prog1.x

现在,根据 gdb 需要,为了启动内置 debug 支持,我们要加上 -g 选项:

gcc [other_flags] -g <source_files> -o <output_file>

例如:

gcc -Wall -Werror -ansi -pedantic-errors -g prog1.c -o prog1.x

启动

输入 gdb 或者 gdb prog1.x ,就能得到如下命令提示符

(gdb)

如果你刚刚没有指定 gdb 哪个文件,那就需要现在来加载:

(gdb) file prog1.x

这里,file 是加载文件的命令,prog1.x 是你要加载的文件名。

gdb 和 Linux shell 有着相似的操作,比如方向键查看历史命令、TAB 键自动补全等

如果对命令不太清楚,可以使用 help 指令:

(gdb) help [command]

运行

要想运行程序,只需要使用

(gdb) run

在这里,如果程序出现错误,你就会看到错误提示。这也正是希望使用 gdb 解决的事情。

断点

断点被用来让程序在运行中的某个地方停下来。指令是 break。比如:

(gdb) break file1.c:6

在 file1.c 的第 6 行设置了一个断点。如果程序运行到了这行,程序就会自动暂停,并且等待你输入其他命令。

我们可以设置任意多个断点。

我们也可以告让程序在某个函数的地方暂停。比如我们有一个函数

int my_func(int a, char *b)

那我们就可以按如下方式设置断点:

(gdb) break my_func

设置完断点后,我们再次执行 run 命令,程序就会开始运行,并在断点处暂停。暂停后,我们使用 continue 命令,让程序继续运行:

(gdb) continue

当然,我们还可以使用 step 让程序仅仅再执行下一行,然后暂停:

(gdb) step

相似的还有 next ,不过如果它遇到函数调用,只会把它当中一个整体执行,而不会进入到函数里面:

(gdb) next

有时候我们需要输入好多 stepnext ,我们只需要按下回车,就可以重复上一条命令。

查询

我们设置断点的目的是让程序暂停,查看当前的状态。那么如何查看状态呢?

我们使用 print 来输出变量的值:

(gdb) print my_var

如果想要 16 进制,则可以用 print/x

(gdb) print/x my_var

我们有时需要关注一个变量,并在它发生变化时暂停程序,查询它的值。这可以用 watch 实现:

(gdb) watch my_var

在上面的例子中,只要 var 改变了,查询就会暂停,输出 var 的旧值和新值。

如果程序中有多个同名变量,那么输出哪个取决于当前程序运行到了哪儿。

其他命令

  • backtrace - produces a stack trace of the function calls that lead to a seg fault (should remind you of Java exceptions)
  • where - same as backtrace; you can think of this version as working even when you’re still in the middle of the program
  • finish - runs until the current function is finished
  • delete - deletes a specified breakpoint
  • info breakpoints - shows information about all declared breakpoints

条件断点

有时候设置了断点,它每次都停下,但我们只想看其中的少数情况,这时可以使用条件断点:

(gdb) break file1.c:6 if i >= ARRAYSIZE

该命令在 file1.c 的第 6 行设置了一个断点,且只有当 i 大于 ARRAYSIZE 的时候才会触发。

指针

比如我们有如下结构体

struct entry {
    int key;
    char *name;
    float price;
    long serial_number;
};

假设现在程序已经执行完了语句

struct entry * e1 = <something>;

这时可以使用下面的语句查看指针位置:

(gdb) print e1

使用下面的指令查看结构体中具体的内容:

(gdb) print e1->key
(gdb) print e1->name
(gdb) print e1->price
(gdb) print e1->serial number

上面的命令和下面的命令时等价的:

(gdb) print (*e1).key
(gdb) print (*e1).name
(gdb) print (*e1).price
(gdb) print (*e1).serial number

如果我们要查看结构体中所有的内容,可以使用命令:

(gdb) print *e1

正如 C 语言中的指针,这种 reference 可以串起来:

(gdb) print list prt->next->next->next->data

Comments

Share This Post