12.1 #[panic_handler]
自定义 panic 处理函数
1分钟内可阅读完
译文 · 基于 The Rustonomicon
#[panic_handler]
#[panic_handler] 用于定义 #![no_std] 应用中 panic! 的行为。#[panic_handler] 必须应用于签名为 fn(&PanicInfo) -> ! 的函数,且二进制 / dylib / cdylib crate 的依赖图中该函数必须恰好出现一次。PanicInfo 的 API 见 [API 文档]。
鉴于 #![no_std] 应用没有标准输出,且部分 #![no_std] 应用(如嵌入式)在开发与发布时需要不同的 panic 行为,使用 panic crate(只包含 #[panic_handler] 的 crate)会很有帮助。这样应用只需链接不同的 panic crate 即可轻松切换 panic 行为。
下面示例:应用根据 dev profile(cargo build)或 release profile(cargo build --release)采用不同 panic 行为。
panic-semihosting crate——用 semihosting 把 panic 消息记录到宿主 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();
// 向宿主 stderr 记录 "panicked at '$reason', src/main.rs:27:4"
writeln!(host_stderr, "{}", info).ok();
loop {}
}
panic-halt crate——panic 时挂起线程;消息被丢弃:
#![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() {
// ..
}