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++}\),调试一遍过!
本文是笔者在考试前一天花一个小时赶工的,可能略有粗糙和纰漏,各位看官老爷如发现错误,可于评论区指出。