#[panic_handler]
#[panic_handler]
用于在 #![no_std]
应用程序中定义 panic!
的行为。 #[panic_handler]
属性必须应用于签名为 fn(&PanicInfo) -> !
的函数,并且此类函数必须在二进制/动态库/cdylib crate 的依赖图中出现一次。 PanicInfo
的 API 可以在 API 文档 中找到。
鉴于 #![no_std]
应用程序没有标准输出,并且一些 #![no_std]
应用程序(例如嵌入式应用程序)需要针对开发和发布使用不同的恐慌行为,因此拥有恐慌 crate(仅包含 #[panic_handler]
的 crate)会很有帮助。这样,应用程序就可以通过简单地链接到不同的恐慌 crate 来轻松地交换恐慌行为。
下面显示了一个示例,其中应用程序根据是使用开发配置文件(cargo build
)还是使用发布配置文件(cargo build --release
)进行编译而具有不同的恐慌行为。
panic-semihosting
crate - 使用半主机将恐慌消息记录到主机 stderr
#![no_std]
use core::fmt::{Write, self};
use core::panic::PanicInfo;
struct HStderr {
// ..
_0: (),
}
impl HStderr {
fn new() -> HStderr { HStderr { _0: () } }
}
impl fmt::Write for HStderr {
fn write_str(&mut self, _: &str) -> fmt::Result { Ok(()) }
}
#[panic_handler]
fn panic(info: &PanicInfo) -> ! {
let mut host_stderr = HStderr::new();
// logs "panicked at '$reason', src/main.rs:27:4" to the host stderr
writeln!(host_stderr, "{}", info).ok();
loop {}
}
panic-halt
crate - 在恐慌时停止线程;消息被丢弃
#![no_std]
use core::panic::PanicInfo;
#[panic_handler]
fn panic(_info: &PanicInfo) -> ! {
loop {}
}
app
crate
#![no_std]
// dev profile
#[cfg(debug_assertions)]
extern crate panic_semihosting;
// release profile
#[cfg(not(debug_assertions))]
extern crate panic_halt;
fn main() {
// ..
}