【Rust】——panic!和不可恢复的错误

本文介绍了Rust中的错误处理机制,重点讲解了panic的使用、不同类型的错误处理(展开和终止)以及如何通过backtrace追踪问题来源,包括bufferoverread的概念和Rust环境变量RUST_BACKTRACE的应用。
摘要由CSDN通过智能技术生成

🎃个人专栏:

🐬 算法设计与分析:算法设计与分析_IT闫的博客-CSDN博客

🐳Java基础:Java基础_IT闫的博客-CSDN博客

🐋c语言:c语言_IT闫的博客-CSDN博客

🐟MySQL:数据结构_IT闫的博客-CSDN博客

🐠数据结构:​​​​​​数据结构_IT闫的博客-CSDN博客

💎C++:C++_IT闫的博客-CSDN博客

🥽C51单片机:C51单片机(STC89C516)_IT闫的博客-CSDN博客

💻基于HTML5的网页设计及应用:基于HTML5的网页设计及应用_IT闫的博客-CSDN博客​​​​​​

🥏python:python_IT闫的博客-CSDN博客

🐠离散数学:离散数学_IT闫的博客-CSDN博客

​​​​​​🥽Linux:​​​​Linux_Y小夜的博客-CSDN博客

🚝Rust:Rust_Y小夜的博客-CSDN博客

欢迎收看,希望对大家有用!

目录

🎯Rust错误处理概述

🎯不可恢复与panic!

🎯使用panic的backtrace


🎯Rust错误处理概述

        突然有一天,代码出问题了,而你对此束手无策。对于这种情况,Rust 有 panic!宏。在实践中有两种方法造成 panic:执行会造成代码 panic 的操作(比如访问超过数组结尾的内容)或者显式调用 panic! 宏。这两种情况都会使程序 panic。通常情况下这些 panic 会打印出一个错误信息,展开并清理栈数据,然后退出。通过一个环境变量,你也可以让 Rust 在 panic 发生时打印调用堆栈(call stack)以便于定位 panic 的原因。

🎯不可恢复与panic!

        当出现 panic 时,程序默认会开始 展开unwinding),这意味着 Rust 会回溯栈并清理它遇到的每一个函数的数据,不过这个回溯并清理的过程有很多工作。

        另一种选择是直接 终止abort),这会不清理数据就退出程序。

        那么程序所使用的内存需要由操作系统来清理。如果你需要项目的最终二进制文件越小越好,panic 时通过在 Cargo.toml 的 [profile] 部分增加 panic = 'abort',可以由展开切换为终止。例如,如果你想要在 release 模式中 panic 时直接终止:

[profile.release]
panic = 'abort'

        一个简单的程序中调用 panic!

fn main() {
    panic!("crash and burn");
}

        最后两行包含 panic! 调用造成的错误信息。第一行显示了 panic 提供的信息并指明了源码中 panic 出现的位置:src/main.rs:2:5 表明这是 src/main.rs 文件的第二行第五个字符。

🎯使用panic的backtrace

        让我们来看看另一个因为我们代码中的 bug 引起的别的库中 panic! 的例子,而不是直接的宏调用。

fn main() {
    let v = vec![1, 2, 3];

    v[99];
}

        这里尝试访问 vector 的第一百个元素(这里的索引是 99 因为索引从 0 开始),不过它只有三个元素。这种情况下 Rust 会 panic。[] 应当返回一个元素,不过如果传递了一个无效索引,就没有可供 Rust 返回的正确的元素。

        C 语言中,尝试读取数据结构之后的值是未定义行为(undefined behavior)。你会得到任何对应数据结构中这个元素的内存位置的值,甚至是这些内存并不属于这个数据结构的情况。这被称为 缓冲区溢出buffer overread),并可能会导致安全漏洞,比如攻击者可以像这样操作索引来读取储存在数据结构之后不被允许的数据。

        我们可以设置 RUST_BACKTRACE 环境变量来得到一个 backtrace。backtrace 是一个执行到目前位置所有被调用的函数的列表。Rust 的 backtrace 跟其他语言中的一样:阅读 backtrace 的关键是从头开始读直到发现你编写的文件。这就是问题的发源地。这一行往上是你的代码所调用的代码;往下则是调用你的代码的代码。这些行可能包含核心 Rust 代码,标准库代码或用到的 crate 代码。让我们将 RUST_BACKTRACE 环境变量设置为任何不是 0 的值来获取 backtrace 看看。

$ RUST_BACKTRACE=1 cargo run
thread 'main' panicked at 'index out of bounds: the len is 3 but the index is 99', src/main.rs:4:5
stack backtrace:
   0: rust_begin_unwind
             at /rustc/e092d0b6b43f2de967af0887873151bb1c0b18d3/library/std/src/panicking.rs:584:5
   1: core::panicking::panic_fmt
             at /rustc/e092d0b6b43f2de967af0887873151bb1c0b18d3/library/core/src/panicking.rs:142:14
   2: core::panicking::panic_bounds_check
             at /rustc/e092d0b6b43f2de967af0887873151bb1c0b18d3/library/core/src/panicking.rs:84:5
   3: <usize as core::slice::index::SliceIndex<[T]>>::index
             at /rustc/e092d0b6b43f2de967af0887873151bb1c0b18d3/library/core/src/slice/index.rs:242:10
   4: core::slice::index::<impl core::ops::index::Index<I> for [T]>::index
             at /rustc/e092d0b6b43f2de967af0887873151bb1c0b18d3/library/core/src/slice/index.rs:18:9
   5: <alloc::vec::Vec<T,A> as core::ops::index::Index<I>>::index
             at /rustc/e092d0b6b43f2de967af0887873151bb1c0b18d3/library/alloc/src/vec/mod.rs:2591:9
   6: panic::main
             at ./src/main.rs:4:5
   7: core::ops::function::FnOnce::call_once
             at /rustc/e092d0b6b43f2de967af0887873151bb1c0b18d3/library/core/src/ops/function.rs:248:5
note: Some details are omitted, run with `RUST_BACKTRACE=full` for a verbose backtrace.

        这里有大量的输出!你实际看到的输出可能因不同的操作系统和 Rust 版本而有所不同。为了获取带有这些信息的 backtrace,必须启用 debug 标识。当不使用 --release 参数运行 cargo build 或 cargo run 时 debug 标识会默认启用,就像这里一样。

  • 26
    点赞
  • 14
    收藏
    觉得还不错? 一键收藏
  • 打赏
    打赏
  • 13
    评论
评论 13
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

Y小夜

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值