GDB 奇技淫巧

yiming564 / 2024-12-19 / 原文

GDB 奇技淫巧

本文面向读者为使用 NOI Linux 的 OIer,因此只介绍 OIer 可能会使用到的功能,对于工程上的功能不会讲述。


今天是 \(\text{CSP-S 2024 Day 0}\),不知道有没有人因为平时依赖 vscode,担心考场上没有合适的调试器呢。

笔者就是这样一个 Joker,但是没有关系,NOI Linux 没有 vscode 插件,我们有 GDB!

GDB 基础运用

你可能以为,GDB 只是一个简陋的 CLI 调试工具,但事实上只需简单的调教和学习,你就可以把它玩出花来。

下面收录了一些 GDB 常用的基础命令(及其简写)

  • start:启动程序并停止在第 \(1\) 行。
  • break[b] x:在第 \(x\) 行设置断点。
  • break[b] x if cond:在第 \(x\) 行设置条件断点断点,当 cond 值为真时触发。
  • run[r]:运行程序
  • continue[c]:在断点处继续运行。
  • info local:查看局部变量。
  • next[n]:单步执行,跳过函数调用。
  • step[s]:单步执行,进入函数调用。
  • finish:结束当前函数。
  • backtrace[bt]:查看函数调用栈。
  • frame[fr]:切换栈帧以查看该栈帧中的局部变量和参数等。
  • display x:持续打印变量。
  • print[p] x:打印变量(一次性)。
  • delete:删除断点,监视点,display 等。
  • list:显示当前运行到的一段代码。

更详细的介绍可以参见 GDB 备忘清单 一文,此处不再赘述。

GDB 高级运用

.gdbinit

在你的用户目录下建立 ~/.gdbinit,它可以在你的 GDB 运行前预输入你自定义的命令。先建立起来,我们后续有用。

TUI 模式

只要给 GDB 传入参数 -tui 就可以打开文本用户界面,这是我们唯一的武器!

使用 TUI 模式,我们可以方便地分屏预览源代码和命令行,并可视化地看到程序运行到了哪里,断点于何处,一切难题迎刃而解!

首先,打开你的 vscode。尽管它只是一个文本编辑器了,但它还可以内置终端,其他软件连这个功能都没有。

给你的程序写好 freopen,并使用 setvbuf(stdout, NULL, _IONBF, 0); 关闭输出缓冲区,这会使你的标准输出的每一个字符被直接写入文件内。这样,在调试的时候,我们直接打开输出的文件,在 vscode 里预览即可。

下面是一个测试程序:

#include <bits/extc++.h>

#define inline __always_inline
template <typename T> inline void read(T &x)
{
	char ch;
	for (ch = getchar(); !isdigit(ch); ch = getchar());
	for (x = 0; isdigit(ch); ch = getchar())	x = x * 10 + (ch - '0');
}

int main()
{
	freopen64("out", "w", stdout);
	setvbuf(stdout, NULL, _IONBF, 0);
	for (int i = 0; i < 10; i++)
		printf("Test\n");
	return 0;
}

为什么要输出到文件这样多此一举?因为 GDB 的 TUI 模式使用 curses 这个库实现,如果再有标准输出会打乱原先文本界面的阵形,导致界面混乱。

然后你可以使用 g++ main.cpp -o main -g 编译你的源文件,并使用 gdb -tui ./main 来试着调试一下,相信你一定很容易学会如何使用。

下图是笔者在 vscode 中调试的实际界面,还是比较人性化的,属于人类可用的范围。

在使用 NOI Linux 时可能没有代码高亮(笔者使用的是 WSL 有代码高亮),但这无伤大雅。

普通效果


当然,你可能会觉得上下结构的窗口结构浪费屏幕空间,没关系!打开 ~/.gdbinit,输入如下内容:

# 定义新窗口布局为左右布局,src 与 cmd 1:1 分屏。
tui new-layout noi-linux {-horizontal src 1 cmd 1} 1 status 0
# 更改为我们自定义的窗口布局
layout noi-linux
# 更改窗口焦点到 cmd(默认在 src)
focus cmd
# 更改代码的 tab 大小(个人喜好)
set tui tab-width 4

然后重新运行 GDB,如果显示异常就略微改变窗口大小,这样就可以左右分屏了,效果如下:

自定义效果


最后,介绍一下 TUI 模式的一些基本的快捷键:

基本快捷键:

  • Ctrl + x o:更改窗口焦点。
  • Ctrl + x s:进入单键命令模式。
  • Ctrl + l:刷新窗口。

单键命令模式:

  • c:断点处继续执行。
  • f:结束当前函数。
  • n:单步执行(跳过函数调用)。
  • s:单步执行(进入函数调用)。
  • v:查看栈变量。
  • w:查看调用栈。
  • q:退出单步调试模式。

GDB CLI 模式的正常的调试命令同样可用。


最后,祝各位 \(\text{CSP-S 2024 rp++}\),调试一遍过!

本文是笔者在考试前一天花一个小时赶工的,可能略有粗糙和纰漏,各位看官老爷如发现错误,可于评论区指出。