在Rust中,有一类错误叫作panic。示例如下:
编译,没有错误,执行这段程序,输出为:
这种情况就引发了一个panic。在这段代码中,我们调用了Option::unwrap()方法,正是这个方法有可能导致panic。根据提示,我们设置一个环境变量RUST_BACKTRACE=1之后再执行这个程序,可以看到这个程序在发生panic时候的函数调用栈。
在Rust中,Panic的实现机制有两种方式:unwind和abort。
在常见的操作系统上,默认情况下,编译器使用的是unwind方式。所以在发生panic的时候,我们可以通过一层层地调用栈找到发生panic的第一现场,就像前面例子展示的那样。
但是,unwind并不是在所有平台上都能获得良好支持的。在某些嵌入式系统上,unwind根本无法实现,或者占用的资源太多。在这种时候,我们可以选择使用abort方式实现panic.
编译器提供了一个选项,供用户指定panic的实现方式。
C++中引入了“异常”这个机制之后,同时也带入了一个“异常安全”(exception safety)的概念。
异常安全存在四种层次的保证:
在Rust中,什么情况下panic会导致bug呢?这种情况的产生需要两个条件:
在unsafe代码中,这种情况非常容易出现。所以,在写unsafe代码的时候,需要对这种情况非常敏感小心,一不小心就可能因为这个原因制造出“内存不安全”。
在不用unsafe的情况下,Panic Safety是基本有保障的。