#[panic_handler]
#[panic_handler]
is used to define the behavior of panic!
in #![no_std]
applications.
The #[panic_handler]
attribute must be applied to a function with signature fn(&PanicInfo) -> !
and such function must appear once in the dependency graph of a binary / dylib / cdylib
crate. The API of PanicInfo
can be found in the API docs.
Given that #![no_std]
applications have no standard output and that some #![no_std]
applications, e.g. embedded applications, need different panicking behaviors for development and for
release it can be helpful to have panic crates, crate that only contain a #[panic_handler]
.
This way applications can easily swap the panicking behavior by simply linking to a different panic
crate.
Below is shown an example where an application has a different panicking behavior depending on
whether is compiled using the dev profile (cargo build
) or using the release profile (cargo build --release
).
panic-semihosting
crate – log panic messages to the host stderr using semihosting:
#![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 – halt the thread on panic; messages are discarded:
#![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() {
// ..
}