Panicking

Panicking is a core part of the Rust language. Built-in operations like indexingare runtime checked for memory safety. When out of bounds indexing is attemptedthis results in a panic.

In the standard library panicking has a defined behavior: it unwinds the stackof the panicking thread, unless the user opted for aborting the program onpanics.

In programs without standard library, however, the panicking behavior is leftundefined. A behavior can be chosen by declaring a #[panichandler] function.This function must appear exactly _once in the dependency graph of a program,and must have the following signature: fn(&PanicInfo) -> !, where PanicInfois a struct containing information about the location of the panic.

Given that embedded systems range from user facing to safety critical (cannotcrash) there's no one size fits all panicking behavior but there are plenty ofcommonly used behaviors. These common behaviors have been packaged into cratesthat define the #[panic_handler] function. Some examples include:

  • panic-abort. A panic causes the abort instruction to be executed.
  • panic-halt. A panic causes the program, or the current thread, to halt byentering an infinite loop.
  • panic-itm. The panicking message is logged using the ITM, an ARM Cortex-Mspecific peripheral.
  • panic-semihosting. The panicking message is logged to the host using thesemihosting technique.

You may be able to find even more crates searching for the panic-handlerkeyword on crates.io.

A program can pick one of these behaviors simply by linking to the correspondingcrate. The fact that the panicking behavior is expressed in the source ofan application as a single line of code is not only useful as documentation butcan also be used to change the panicking behavior according to the compilationprofile. For example:

  1. #![no_main]
  2. #![no_std]
  3. // dev profile: easier to debug panics; can put a breakpoint on `rust_begin_unwind`
  4. #[cfg(debug_assertions)]
  5. extern crate panic_halt;
  6. // release profile: minimize the binary size of the application
  7. #[cfg(not(debug_assertions))]
  8. extern crate panic_abort;
  9. // ..

In this example the crate links to the panic-halt crate when built with thedev profile (cargo build), but links to the panic-abort crate when builtwith the release profile (cargo build —release).

An example

Here's an example that tries to index an array beyond its length. The operationresults in a panic.

  1. #![no_main]
  2. #![no_std]
  3. extern crate panic_semihosting;
  4. use cortex_m_rt::entry;
  5. #[entry]
  6. fn main() -> ! {
  7. let xs = [0, 1, 2];
  8. let i = xs.len() + 1;
  9. let _y = xs[i]; // out of bounds access
  10. loop {}
  11. }

This example chose the panic-semihosting behavior which prints the panicmessage to the host console using semihosting.

  1. $ cargo run
  2. Running `qemu-system-arm -cpu cortex-m3 -machine lm3s6965evb (..)
  3. panicked at 'index out of bounds: the len is 3 but the index is 4', src/main.rs:12:13

You can try changing the behavior to panic-halt and confirm that no message isprinted in that case.