gdb 基本使用

本篇博客主要是对《LinuxC》相关章节中的学习笔记以及记录。在学习的过程中,为了减缓遗忘,以及将来需要时可以随时查阅自己的知识库,故整理如下。

单步执行和跟踪函数调用

首先写一段有问题的测试代码:

/* main.c */
#include<stdio.h>

int add_range(int low, int high)
{
	int i, sum;
	for (i = low; i <= high; i++)
		sum = sum + i;
	return sum;
}

int main(void)
{
	int result[100];
	result[0] = add_range(1, 10);
	result[1] = add_range(1, 100);
	printf("result[0]=%d\nresult[1]=%d\n", result[0], result[1]);
	return 0;
}

接下来,对于 gdb 的使用,我们主要是以调试这个程序的方式来理解。

结果显然错误。

然后我们来调试,

$ gcc -g .\main.c -o main
$ gdb .\main.exe
GNU gdb (GDB) 8.1
Copyright (C) 2018 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.  Type "show copying"
and "show warranty" for details.
This GDB was configured as "x86_64-w64-mingw32".
Type "show configuration" for configuration details.
For bug reporting instructions, please see:
<http://www.gnu.org/software/gdb/bugs/>.
Find the GDB manual and other documentation resources online at:
<http://www.gnu.org/software/gdb/documentation/>.
For help, type "help".
Type "apropos word" to search for commands related to "word"...
Reading symbols from .\main.exe...done.
(gdb)

-g 的作用是在目标文件中加入源代码的信息,比如目标文件的机器指令对应源代码的第几行,但并不是把整个源文件嵌入到目标文件中。所以在调试目标文件时必须保证 gdb 也能找到源文件。

help 命令。

查看命令的类别。

help files

查看 files 类别下有那些命令可以用。

list 1

从第一行开始列出源代码。一次只列 10 行。

list 命令可以简写成为 l

list

接上一条,继续从 11 行列出源代码。

直接回车。

重复上一条命令。

l add_range

列出一个函数的源代码。

quit

退出 gdb 环境。

start

开始执行命令。

这表示停在 main 函数中变量定义之后的第一条语句处等待我们发命令,gdb 列出这条语句表示它还没执行,并且马上要执行。

next(简写为 n)。

接上条。一条一条执行语句。

start

重新来过。

step(简写为 s)。

进入函数中去执行。

backtrace(简写为 bt)。

在函数中查看函数调用的栈帧。

info(简写为 i)。

查看局部变量(locals)的值:

frame(简写为 f)。

选择栈帧。

示例,查看 main 函数当前局部变量的值,先用 frame 命令选择 1 号栈帧然后再查看局部变量:

print(简写为 p)。

打印变量的值。

示例,打印 sum 的值:

这里的 $1 表示 gdb 保存着这些中间结果,$ 后面的编号会自动增长,在命令中可以用 $1、$2、$3 等编号代替相应的值。

finish

让程序一直运行到当前函数返回为止。

按:这里出了一个大问题,我现在的 mingw 中的 gdb 版本是 gdb8.1,在这个版本中,执行 finish 命令会直接退出 gdb!无奈之下,换了 mingw 的版本,现在继续整理。

按:改换了 gdb 版本之后,这个程序的第一个结果变得正确了。但是这不是很重要,我们只是需要理解其背后的逻辑。

接下来,继续调试:

然后发现 sum 有问题。

之后我们就可以退出 gdb 去修改程序了。

set

但是,我们也可以使用 set 命令去立刻把 sum 的值改过来,然后继续执行代码,继续调试,

修改变量的值也可以用 print 命令,我们可以用 print 来修改变量的值,或者调用函数:

按:printf 的返回值表示实际要打印的字符数,同时,这里要明确将 printf 的返回值 cast 成 int 类型。

命令 描述
backtrace(或 bt) 查看各级函数调用及参数
finish 执行到当前函数返回,然后停下来等待命令
frame(或 f) 帧编号 选择栈帧
info(或 i) locals 查看当前栈帧局部变量的值
list(或 l) 列出源代码,接着上次的位置往下列,每次列 10 行
list 行号 列出从第几行开始的源代码
list 函数名 列出某个函数的源代码
next(或 n) 执行下一行语句
print(或 p) 打印表达式的值,通过表达式可以修改变量的值或者调用函数
set var 修改变量的值
start 开始执行程序,停在 main 函数第一行语句前面等待命令
step(或 s) 执行下一行语句,如果有函数调用则进入到函数中

断点

测试代码:

/* main.c */
#include<stdio.h>

int main(void)
{
	int sum = 0, i = 0;
	char input[5];

	while (1) {
		scanf("%s", input);
		for (i = 0; input[i] != '\0', i++)
			sum = sum * 10 + input[i] - '0';
		printf("input=%d\n", sum);
	}
	return 0;
}

gdb 基本使用
http://fanyfull.github.io/2021/11/30/gdb-基本使用/
作者
Fany Full
发布于
2021年11月30日
许可协议