Rust-Panic

什么是panic

在Rust中,有一类错误叫作panic。示例如下:

在这里插入图片描述
编译,没有错误,执行这段程序,输出为:

在这里插入图片描述
这种情况就引发了一个panic。在这段代码中,我们调用了Option::unwrap()方法,正是这个方法有可能导致panic。根据提示,我们设置一个环境变量RUST_BACKTRACE=1之后再执行这个程序,可以看到这个程序在发生panic时候的函数调用栈。

Panic实现机制

在Rust中,Panic的实现机制有两种方式:unwind和abort。

  • unwind方式在发生panic的时候,会一层一层地退出函数调用栈,在此过程中,当前栈内的局部变量还可以正常析构。
  • abort方式在发生panic的时候,会直接退出整个程序。

在常见的操作系统上,默认情况下,编译器使用的是unwind方式。所以在发生panic的时候,我们可以通过一层层地调用栈找到发生panic的第一现场,就像前面例子展示的那样。

但是,unwind并不是在所有平台上都能获得良好支持的。在某些嵌入式系统上,unwind根本无法实现,或者占用的资源太多。在这种时候,我们可以选择使用abort方式实现panic.

编译器提供了一个选项,供用户指定panic的实现方式。

Panic Safety

C++中引入了“异常”这个机制之后,同时也带入了一个“异常安全”(exception safety)的概念。

异常安全存在四种层次的保证:

  • No-throw——这种层次的安全性保证了所有的异常都在内部正确处理完毕,外部毫无影响;
  • Strong exception safety——强异常安全保证可以保证异常发生的时候,所有的状态都可以“回滚”到初始状态,不会导致状态不一致的问题;
  • Basic exception safety——基本异常安全保证可以保证异常发生的时候不会导致资源泄漏;
  • No exception safety——没有任何异常安全保证。

在Rust中,什么情况下panic会导致bug呢?这种情况的产生需要两个条件:

  • panic导致了数据结构内部的状态错误;
  • 这个错误的状态会在以后被观测到。

在unsafe代码中,这种情况非常容易出现。所以,在写unsafe代码的时候,需要对这种情况非常敏感小心,一不小心就可能因为这个原因制造出“内存不安全”。

在不用unsafe的情况下,Panic Safety是基本有保障的。

你可能感兴趣的:(Rust,rust,开发语言,后端)