#debugging #start #cross-platform #script #gdb #hook #state

debug-here

一个宏,可以节省启动调试所需的时间

6 个版本

使用旧的 Rust 2015

0.2.2 2019 年 3 月 22 日
0.2.1 2019 年 3 月 22 日
0.1.2 2018 年 10 月 19 日
0.1.1 2018 年 9 月 26 日

#13 in #gdb

Download history 32/week @ 2024-03-11 21/week @ 2024-03-18 27/week @ 2024-03-25 87/week @ 2024-04-01 35/week @ 2024-04-08 21/week @ 2024-04-15 13/week @ 2024-04-22 10/week @ 2024-04-29 49/week @ 2024-05-06 40/week @ 2024-05-13 32/week @ 2024-05-20 34/week @ 2024-05-27 48/week @ 2024-06-03 57/week @ 2024-06-10 67/week @ 2024-06-17 59/week @ 2024-06-24

232 每月下载量
用于 3 crates

MIT/Apache

22KB
223 行代码(不包括注释)

debug-here:一个跨平台的 Rust 调试器钩子

问题

调试器是检查您试图理解程序状态的一种很好的方法,但实际上开始使用调试器可能会有一些仪式。您需要确定您关心的可执行文件名称。如果您通过其他人编写的(甚至可能是您自己编写的)多层脚本运行程序,这可能比您想象的要困难。一旦您获得了可执行文件名称,您就必须使用 rust-gdb exe(如果您使用包装脚本,您必须安排您的脚本这样做)来启动它。现在您已经在 gdb 下启动了程序,您必须设置断点。这不是很多工作,但我发现自己经常这样做,所以这可能会变得有点烦人。

一种替代方法是让您的程序进入某种睡眠或循环状态,在命令行中搜索 PID,然后使用 gdb -pid 连接。这通常需要更多的工作(再次,不是很多工作,但足以让人烦恼),因此人们只有在无法从终端启动相关程序时才会这样做。

使 Rust 中的调试过程更简单

这个 crate 自动化了说服程序等待调试器连接的过程。进入调试器应该和写入一个 println! 语句一样简单。这个 crate 就是这样做的。

设置

Linux 特定设置

如果您使用 Linux 并且想使用 xterm 作为您的终端模拟器,您需要安装调试器包装器(出于历史原因,该包装器称为 debug-here-gdb-wrapper)。并非所有的终端模拟器都允许您将额外的参数传递给您调用的程序作为 shell,因此 debug-here-gdb-wrapper 将安排您的调试器后端执行所有正确的命令。

cargo install debug-here-gdb-wrapper

或者,您可以使用 alacritty 作为您的终端模拟器,在这种情况下,您不需要处理 debug-here-gdb-wrapper。如果您已经将 alacritty 添加到您的路径中,debug-here 将自动选择使用它而不是 xterm,因此安装后无需特殊设置。

Windows 特定设置

debug-here 使用 Windows 即时调试来允许您使用 Visual Studio 调试代码,因此您必须有一个正常工作的 Visual Studio 安装。

常规设置

将 debug-here 添加到您想要工作的 crate 的依赖中。

debug-here = "0.2"

使用方法

将以下代码添加到您的 lib.rsmain.rs 中,以便在需要进入调试器的地方: #[macro_use] extern crate debug_here;,然后在哪里想要进入调试器,只需编写 debug_here!() 宏。当您的程序第一次到达该点时,它将在 debug_here!() 宏之后立即启动适合您平台的调试器并附加到您的进程。您可以四处探索并开始逐步执行您的程序。如果您到达另一个 debug_here!() 宏调用,您不必担心更多调试器终端会左左右右地生成。每个程序中 debug_here!() 仅触发一次。

Windows 使用说明

Visual Studio 将在 debug_break_wrapper 函数的末尾将您放入调试器中。您可以多次按 F10 返回到调用 debug_here!() 宏的代码位置。

Visual Studio 是 Windows 上唯一支持的调试器。

Unixy 使用说明

在 Linux 和 macOS 上,您可以选择使用 rust-gdbrust-lldb 作为调试器后端。如果您计划在代码中保留 debug_here!() 宏,您应避免强制使用特定的后端,因为并非所有后端都在所有平台上表现良好。例如,Windows 不会与 gdblldb 一起使用。

支持的终端模拟器

目前 debug-here 在 Linux 上支持 alacrittyxterm,在 macOS 上支持 Terminal.app。如果您在路径中安装了 alacritty,它将使用它,假设您宁愿使用一个不太标准的终端模拟器,因为您已经费心安装了它。如果没有在路径中安装 alacritty,它将回退到 xterm

平台

目前 debug-here 仅在 Linux、macOS 和 Windows 上工作。默认情况下,在 Linux 上使用 rust-gdb,在 macOS 上使用 rust-lldb,在 Windows 上使用 Visual Studio。在 macOS 上默认使用 rust-lldb 的主要原因是为了避免获得正确签名的 gdb 的麻烦。

尽管可能,但 debug-here 可能不会增长对更多平台的支持,尽管 Windows 可能会增长对 gdb 和 lldb 的支持。我乐于接受更多异类平台的补丁,尽管测试可能存在问题。

示例:错误的阶乘

我有一个非常重要的 Rust 程序,名为 debug-me,该程序计算 5 的阶乘。或者至少它是 supposed to。目前它告诉我 5 的阶乘是 0,这看起来不太对劲。以下是我的 main.rs

fn factorial(n: usize) -> usize {
    let mut res = 1;
    for i in 0..n {
        res *= i;
    }
    res
}

fn main() {
    println!("The factorial of 5 is {}!", factorial(5));
}

你可能看得出来问题所在,但我看不到,因为我没有调试器就无法行动。为了找出问题所在,我打算使用“在这里调试”来帮助我。首先,我会确保使用以下命令安装“在这里调试”的调试器shim:cargo install debug-here-gdb-wrapper。现在,我将“在这里调试”添加到我的阶乘crate的Cargo.toml文件中。

[dependencies]
debug-here = "0.1"

然后我会添加这一行

#[macro_use] extern crate debug_here;

到我的源文件。现在它看起来是这样的

#[macro_use] extern crate debug_here;

fn factorial(n: usize) -> usize {
    let mut res = 1;
    for i in 0..n {
        res *= i;
    }
    res
}

fn main() {
    println!("The factorial of 5 is {}!", factorial(5));
}

我的循环确实在计数并将结果变量乘以越来越大的数字。我觉得它应该能工作,但我还是要通过“在这里调试”逐步执行几次循环来查看发生了什么。是时候设置我的断点了。

#[macro_use] extern crate debug_here;

fn factorial(n: usize) -> usize {
    let mut res = 1;
    debug_here!();
    for i in 0..n {
        res *= i;
    }
    res
}

fn main() {
    println!("The factorial of 5 is {}!", factorial(5));
}

就像println!一样简单!现在,我使用以下命令运行我的程序:cargo run。一个终端窗口弹出来,里面有一个显示gdb shell的窗口

debug_me::factorial (n=5) at debug-me/src/main.rs:6
6           for i in 0..n {
(gdb)

查看我的源代码,我发现res是一个有趣的变量,值得跟踪,所以我让gdb保持通知我。

(gdb) disp res
1: res = 1

现在,我会逐步通过几次循环。

(gdb) n
7               res *= i;
1: res = 1
(gdb) n
6           for i in 0..n {
1: res = 0
(gdb) n
7               res *= i;
1: res = 0

看起来在第一次循环迭代中,res变成了0。回顾源代码,我发现这是因为计数器从0开始。我将退出调试器并修复它。

如果你想亲自尝试这个示例,你只需克隆以下仓库:https://github.com/ethanpailes/debug-here并运行以下命令

 > cargo install debug-here-gdb-wrapper # if you are on linux
 > cd debug-here/debug-me
 > cargo run

你应该会看到一个带有调试器shell的终端弹出。阶乘例程中还有一个错误。试着找到它。

依赖关系

~2.6–4MB
~75K SLoC