Rust对可靠性的执着也伸到了错误处理
Rust将错误组合成两个主要的类别:可恢复错误和不可恢复错误
大多数语言并不区分这两类错误,并采用类似异常这样的方式统一处理它们,Rust没有异常,但是有可恢复的错误Rust<T,E>,和不可恢复的错误panic
Rust有panic!宏。当执行它时,程序会打印一个错误信息,展开并清理栈数据,接着退出。这种方式适用于程序出现了我们不知道如何处理的错误
对应panic时的栈展开终止
当程序遇到panic时,程序默认会开始展开,这意味着Rust会回溯并清理它遇到的每个函数的数据,但这个清理过程有很多工作,另一种方式是直接终止,清理工作由操作系统来完成。如果你需要项目的最终二进制文件越小越好,通过在Cargo.toml的[profile]部分增加panic = ‘abort’,可以由展开切换为终止。例如你想要在release模式中panic时直接终止
[profile.release]
panic = 'abort'
调用一个panic!
fn main() {
panic!("crash and burn");
}
//
thread 'main' panicked at 'crash and burn', src/main.rs:2:5
stack backtrace:
0: std::panicking::begin_panic
at /rustc/c8dfcfe046a7680554bf4eb612bad840e7631c4b/library/std/src/panicking.rs:541:12
1: vectors::main
at ./src/main.rs:2:5
2: core::ops::function::FnOnce::call_once
at /rustc/c8dfcfe046a7680554bf4eb612bad840e7631c4b/library/core/src/ops/function.rs:227:5
note: Some details are omitted, run with `RUST_BACKTRACE=full` for a verbose backtrace.
终端进程“cargo 'run', '--package', 'vectors', '--bin', 'vectors'”已终止,退出代码: 101。
根据运行结果我们发现出错在第二行的第五个字符
使用panic!的backtrace
let v = vec![1,2,3];
let x = v[99];
//
thread 'main' panicked at 'index out of bounds: the len is 3 but the index is 99', src/main.rs:3:17
note: Some details are omitted, run with `RUST_BACKTRACE=full` for a verbose backtrace.
程序运行时会输出错误信息
但是你可能看到类似以下的输出:这是因为backtrace,backtrace是执行到目前位置所有被调用的函数列表,阅读backtrace的关键是从头开始读直到发现你编写的文件,这一行往上是你的代码所调用的代码,往下则是调用你的代码的代码。这些可能包含核心的rust代码,标准库代码或用到的trace代码。将RUST_BACKTRACE环境变量设置为任何不是0的值来获取backtrace
Finished dev [unoptimized + debuginfo] target(s) in 1.24s
Running `target/debug/vectors`
thread 'main' panicked at 'index out of bounds: the len is 3 but the index is 99', src/main.rs:3:17
stack backtrace:
0: rust_begin_unwind
at /rustc/c8dfcfe046a7680554bf4eb612bad840e7631c4b/library/std/src/panicking.rs:515:5
1: core::panicking::panic_fmt
at /rustc/c8dfcfe046a7680554bf4eb612bad840e7631c4b/library/core/src/panicking.rs:92:14
2: core::panicking::panic_bounds_check
at /rustc/c8dfcfe046a7680554bf4eb612bad840e7631c4b/library/core/src/panicking.rs:69:5
3: <usize as core::slice::index::SliceIndex<[T]>>::index
at /rustc/c8dfcfe046a7680554bf4eb612bad840e7631c4b/library/core/src/slice/index.rs:184:10
4: core::slice::index::<impl core::ops::index::Index<I> for [T]>::index
at /rustc/c8dfcfe046a7680554bf4eb612bad840e7631c4b/library/core/src/slice/index.rs:15:9
5: <alloc::vec::Vec<T,A> as core::ops::index::Index<I>>::index
at /rustc/c8dfcfe046a7680554bf4eb612bad840e7631c4b/library/alloc/src/vec/mod.rs:2432:9
6: vectors::main
at ./src/main.rs:3:17
7: core::ops::function::FnOnce::call_once
at /rustc/c8dfcfe046a7680554bf4eb612bad840e7631c4b/library/core/src/ops/function.rs:227:5
note: Some details are omitted, run with `RUST_BACKTRACE=full` for a verbose backtrace.
这儿有很多输出,但你看到的结果可能因操作系统或Rust版本不同而不同。为了获取带有这些信息的backtrace,必须启用debug标识,当不使用 – release参数运行cargo build 或 cargo run时debug标识会默认启用,就像这里一样
backtrace 的6行指出了我们项目中造成问题的行,修复这个panic的方法是不要在只包含三个项的vector中请求索引是100的元素