The panic handler¶
Level: 301 · deep dive
One line: In std a panic prints a message, unwinds and exits with 101 because somebody wrote that code; in #![no_std] nobody did, so the program must supply exactly one #[panic_handler] — a function that takes &PanicInfo and never returns.
Stub — an outline, not a lesson. There is no runnable example behind this page yet, so nothing on it has been through the check that backs every other claim in this library. The bullets below are the questions the finished page has to answer.
What it has to cover¶
- The refusal: a
#![no_std]binary with no handler stops aterror: `#[panic_handler]` function required, but not found(1.98.0). The shape it wants isfn(&core::panic::PanicInfo) -> !, and the never type is what forbids returning. - The second refusal, the one met first on a laptop: a
no_stdstaticlib built for the host with the default strategy fails with "unwinding panics are not supported without std".-C panic=abort—panic = "abort"in a Cargo profile ↗ — makes it build. Bare-metal targets already default to it:rustc --print cfg --target thumbv7em-none-eabihfprintspanic="abort". - What std's handler did that you now choose: the
thread 'main' panicked atline, the backtrace note, unwinding through destructors, exit code 101. Which of those can a chip with no stderr and no parent process do at all? - The usual handlers and what each costs during bring-up: loop forever, reset the chip, write the message to a debug probe, halt for a debugger. The
panic-halt↗ crate is the one-line version of the first. - What
PanicInfo↗ carries —location()(stable 1.10.0) andmessage()(stable 1.81.0) — and whether formatting that message pulls incore::fmtcode a small flash chip cannot spare. - Exactly one per program: a crate that defines a handler next to a dependency that also defines one fails with
error[E0152]: found duplicate lang item `panic_impl`(1.98.0). So which crate should own it — why does ano_stdlibrary leave it to the binary, the same program-wide rule as#[global_allocator]? - Out-of-memory in
no_stdroutes here too, sincealloc's defaulthandle_alloc_errorcallspanic!when nothing linksstd— see Out of memory.
The trap it exists for¶
Writing loop {} because it is the shortest function that returns !. It is a correct handler, and it turns every unwrap during bring-up into a board that silently stops — no message, no line number, nothing on any wire to say which call failed.
Where this sits¶
What a panic costs covers the unwinding panic, catch_unwind and exit code 101 under std; this page covers only what replaces all of that when std is gone.
See also¶
- What a panic costs — the
panic = "abort"bullet this page starts from - Reading a backtrace — the output a device handler gives up
- The never type
!— why the handler's return type is not() core,allocandstd— why the handler is missing in the first place- What runs before
main— the other half of the runtime you now write - GLOSSARY.md — panic and unwinding, as the rest of the library uses them
- The Embedded Rust Book: Panicking ↗
- The Rust Reference: the
panic_handlerattribute ↗
If you are coming from another language¶
- C. C has no panic, so the closest thing is a failed
assertcallingabort()— and on bare metal, whatabortdoes is whatever the C library you linked decided. Rust turns that decision into a required function with a checked signature, and refuses to build a binary that has not made it. - C++. An uncaught exception ends in
std::terminate, and-fno-exceptionsremoves exceptions from a build altogether.panic = "abort"is the Rust version of that trade: no unwinding, so no destructors run on the way out. - Go. A panic nobody recovers ends the whole program with a stack trace, and the runtime owns how that looks — A panic ends the whole program ↗. Without
std, Rust hands you that last step as your own function.
Po polsku¶
W zwykłym programie panika wypisuje komunikat, odwija stos i kończy proces kodem 101 — ale tylko dlatego, że ktoś to napisał w std. Bez biblioteki standardowej trzeba samemu dostarczyć dokładnie jedną funkcję z atrybutem #[panic_handler], która przyjmuje &PanicInfo i nigdy nie wraca (typ !). Na mikrokontrolerze nie ma gdzie wypisać komunikatu ani procesu, który można zakończyć, więc wybór jest prawdziwą decyzją projektową: pętla bez końca, reset układu albo wysłanie komunikatu przez sondę debugującą.
Szukaj po polsku: obsługa paniki bez std · panika na mikrokontrolerze · rust panic_handler no_std · rust unwinding panics are not supported without std · rust duplicate lang item panic_impl