Panic Strategies & Binary Size

+15 Mana ✨

panic = "unwind" (default)

  • Runs destructors when panicking
  • Supports catch_unwind
  • Larger binary (unwinding tables)
  • Slower panics

panic = "abort"

  • Program terminates immediately
  • No destructors run
  • Smaller binary
  • Faster panics (they're rare anyway)
toml
[profile.release]
panic = "abort"

When to Use Each

Use CaseStrategy
Librariesunwind (let caller decide)
Applicationsabort (usually fine)
Need catch_unwindunwind
Embedded/WASMabort
Minimize binaryabort

Binary Size Reduction

toml
[profile.release]
panic = "abort"         # Remove unwinding
strip = true            # Remove symbols
opt-level = "z"         # Size optimization
lto = true              # Dead code elimination
codegen-units = 1       # Better DCE

More Techniques

bash
# Use cargo-bloat to find what's taking space
cargo install cargo-bloat
cargo bloat --release

# Strip after build
strip target/release/myapp

# UPX compression (controversial)
upx --best target/release/myapp

std vs no_std

rust
// Smallest possible binary (no std)
#![no_std]
#![no_main]

#[panic_handler]
fn panic(_: &core::panic::PanicInfo) -> ! {
    loop {}
}

Code Examples

rust
// Using catch_unwind (requires panic="unwind")
use std::panic;

fn might_panic() {
    panic!("oops!");
}

fn main() {
    let result = panic::catch_unwind(|| {
        might_panic();
    });
    
    match result {
        Ok(()) => println!("No panic"),
        Err(_) => println!("Caught a panic!"),
    }
    
    println!("Program continues...");
}

// Note: catch_unwind is NOT for normal error handling!
// Use it for:
// - FFI boundaries (don't let panics cross into C)
// - Thread pools (don't crash the whole pool)
// - Plugin systems
✓ Completed