恐慌
的不可恢复的错误!
有时,你的代码中会发生坏事,你无能为力
它。在这些情况下,Rust 具有宏。有两种方法可以导致
Panic 在实践中:通过执行导致代码 panic 的作(例如
访问超过末尾的数组)或通过显式调用宏。
在这两种情况下,我们都会在我们的程序中引起恐慌。默认情况下,这些 panic 将
打印失败消息,展开,清理堆栈,然后退出。通过
环境变量中,您还可以让 Rust 在
panic 的发生是为了更容易追踪 panic 的来源。panic!
panic!
展开堆栈或中止以响应 panic
默认情况下,当 panic 发生时,程序开始展开,这意味着 Rust 会回到堆栈中,并清理每个函数中的数据 遇到。然而,走回去清理是一项艰巨的工作。锈 因此,允许您选择立即中止的替代方案, 这将结束程序而不进行清理。
然后,程序正在使用的内存将需要由
操作系统。如果你需要将生成的二进制文件设为
尽可能小,你可以通过以下方式在 panic 时从 unwind 切换到 aborting
添加到 Cargo.toml 文件中的相应部分。例如,如果你想在 release 模式下在 panic 时中止,
添加以下内容:panic = 'abort'
[profile]
[profile.release]
panic = 'abort'
让我们尝试在一个简单的程序中调用panic!
文件名: src/main.rs
fn main() { panic!("crash and burn"); }
当您运行该程序时,您将看到如下内容:
$ cargo run
Compiling panic v0.1.0 (file:///projects/panic)
Finished `dev` profile [unoptimized + debuginfo] target(s) in 0.25s
Running `target/debug/panic`
thread 'main' panicked at src/main.rs:2:5:
crash and burn
note: run with `RUST_BACKTRACE=1` environment variable to display a backtrace
调用 to 会导致最后两行中包含的错误消息。
第一行显示了我们的 panic 消息和源代码中的位置,其中
发生 panic: src/main.rs:2:5 表示这是第二行
src/main.rs 文件的第五个字符。panic!
在这种情况下,指示的行是我们代码的一部分,如果我们转到该行
行,我们会看到 macro 调用。在其他情况下,调用可能会
位于代码调用的代码中,以及由
错误消息将是宏所在的其他人的代码
called 调用的 API 代码,而不是最终导致 call 的代码行。panic!
panic!
panic!
panic!
我们可以使用调用来源的函数的回溯来计算
找出导致问题的代码部分。了解如何使用
回溯,让我们看看另一个例子,看看当
由于代码中的 bug 而不是
从我们的代码中直接调用宏。示例 9-1 有一些代码
尝试访问超出有效索引范围的 vector 中的索引。panic!
panic!
panic!
文件名: src/main.rs
fn main() { let v = vec![1, 2, 3]; v[99]; }
在这里,我们尝试访问 vector 的第 100 个元素(位于
索引 99,因为索引从零开始),但向量只有 3 个
元素。在这种情况下,Rust 会 panic。using 应该返回
一个元素,但如果你传递了一个无效的索引,则没有 Rust
可以返回这里,那将是正确的。[]
在 C 语言中,尝试读取数据结构末尾之外的内容是 undefined 行为。您可能会获得内存中位置的任何内容 对应于数据结构中的该元素,即使内存 不属于该结构。这称为缓冲区过度读取,并且可能会 如果攻击者能够纵索引,则会导致安全漏洞 以这样一种方式读取数据,他们不应该被允许读取 数据结构。
为了保护程序免受此类漏洞的影响,如果尝试读取 元素中,Rust 将停止执行并拒绝 继续。让我们试一试,看看:
$ cargo run
Compiling panic v0.1.0 (file:///projects/panic)
Finished `dev` profile [unoptimized + debuginfo] target(s) in 0.27s
Running `target/debug/panic`
thread 'main' panicked at src/main.rs:4:6:
index out of bounds: the len is 3 but the index is 99
note: run with `RUST_BACKTRACE=1` environment variable to display a backtrace
此错误指向 main.rs 的第 4 行,我们尝试访问 中向量的索引。99
v
该行告诉我们,我们可以设置环境
变量来回溯导致错误的确切原因。回溯是已调用的所有函数的列表,用于实现此
点。Rust 中的回溯与其他语言一样工作:关键
读取回溯是从顶部开始读取,直到您看到
写。这就是问题的根源。该点上方的线条
是您的代码调用的代码;以下几行是将
法典。这些前后行可能包括核心 Rust 代码、标准
库代码或您正在使用的 crate 中。让我们尝试通过
将环境变量设置为除 之外的任何值。
示例 9-2 显示了与你将看到的类似的输出。note:
RUST_BACKTRACE
RUST_BACKTRACE
0
$ RUST_BACKTRACE=1 cargo run
thread 'main' panicked at src/main.rs:4:6:
index out of bounds: the len is 3 but the index is 99
stack backtrace:
0: rust_begin_unwind
at /rustc/07dca489ac2d933c78d3c5158e3f43beefeb02ce/library/std/src/panicking.rs:645:5
1: core::panicking::panic_fmt
at /rustc/07dca489ac2d933c78d3c5158e3f43beefeb02ce/library/core/src/panicking.rs:72:14
2: core::panicking::panic_bounds_check
at /rustc/07dca489ac2d933c78d3c5158e3f43beefeb02ce/library/core/src/panicking.rs:208:5
3: <usize as core::slice::index::SliceIndex<[T]>>::index
at /rustc/07dca489ac2d933c78d3c5158e3f43beefeb02ce/library/core/src/slice/index.rs:255:10
4: core::slice::index::<impl core::ops::index::Index<I> for [T]>::index
at /rustc/07dca489ac2d933c78d3c5158e3f43beefeb02ce/library/core/src/slice/index.rs:18:9
5: <alloc::vec::Vec<T,A> as core::ops::index::Index<I>>::index
at /rustc/07dca489ac2d933c78d3c5158e3f43beefeb02ce/library/alloc/src/vec/mod.rs:2770:9
6: panic::main
at ./src/main.rs:4:6
7: core::ops::function::FnOnce::call_once
at /rustc/07dca489ac2d933c78d3c5158e3f43beefeb02ce/library/core/src/ops/function.rs:250:5
note: Some details are omitted, run with `RUST_BACKTRACE=full` for a verbose backtrace.
这是很大的产出!您看到的确切输出可能会有所不同,具体取决于
在您的作系统和 Rust 版本上。为了使用 this 获取回溯
信息,则必须启用调试符号。调试符号由
default (无论是否使用该标志时),
就像我们在这里一样。cargo build
cargo run
--release
在示例 9-2 的输出中,回溯的第 6 行指向 导致问题的项目:src/main.rs 的第 4 行。如果我们不想 我们的计划恐慌,我们应该从指向的位置开始调查 到的第一行提到我们编写的文件。在示例 9-1 中,我们 故意编写了会 panic 的代码,解决 panic 的方法是不要 请求超出 vector 索引范围的元素。当您的代码 panic 的 panic 中,您需要弄清楚代码正在采取什么作 替换为哪些值会导致 panic 以及代码应该做什么。
我们会回到我们应该和不应该使用
处理 “To panic!
或者不要惊慌!
部分
章。接下来,我们将了解如何使用 从错误中恢复。panic!
panic!
Result
本文档由官方文档翻译而来,如有差异请以官方英文文档(https://doc.rust-lang.org/)为准