If you find this helpful, please like, bookmark, and follow. To keep learning along, follow this series.
9.1.1 Rust Error Handling Overview
Rust is extremely reliable, and that reliability extends to error handling. In most cases, Rust forces you to think about where errors might occur and then ensures at compile time that they are handled properly.
In Rust, errors are divided into two broad categories:
- Recoverable errors: for example, a file not being found. In that case, you can pass the error message to the user and let the user try again.
- Unrecoverable errors: another way to say “bug”, for example, an out-of-bounds index.
Most other programming languages do not make this distinction deliberately. They usually handle both through a single mechanism such as exceptions. Rust does not have a similar exception mechanism.
- For recoverable errors, Rust provides the
Result<T, E>type, which will be covered in the next article. - For unrecoverable errors, Rust provides the
panic!macro. When this macro is executed, the program immediately stops running.
9.1.2 panic!
Sometimes something terrible happens in code, and the developer has no real way to deal with it. To handle this situation, Rust provides the panic! macro.
When this macro runs, the following happens:
- It prints an error message.
- Then it unwinds and cleans up the call stack.
- It exits the program.
9.1.3 When panic! Happens: Unwinding or Aborting the Call Stack
Unwinding the call stack does a lot of work, because Rust walks back through the stack and cleans up data from every function it encounters along the way.
By contrast, Rust also offers the option to abort the call stack. This means no cleanup is performed; the program stops immediately, and the memory used by the program is left for the operating system to clean up later.
If you want a smaller binary, change the setting from “unwind” to “abort”: set panic = "abort" in the appropriate profile section of Cargo.toml.
Here is my Cargo.toml as an example:
[package]
name = "RustStudy"
version = "0.1.0"
edition = "2021"
[dependencies]
rand = "0.8.5"
[profile.release]
panic = "abort"
profile.release means running in release mode.
9.1.4 The panic! Macro
Let’s look at an example of the panic! macro:
fn main() {
panic!("Something went wrong");
}
This is a very simple example. The argument to the panic! macro is the error message, and it will be printed when the program stops.
Output:
thread 'main' panicked at src/main.rs:2:5:
Something went wrong
stack backtrace:
0: rust_begin_unwind
at /rustc/90b35a6239c3d8bdabc530a6a0816f7ff89a0aaf/library/std/src/panicking.rs:665:5
1: core::panicking::panic_fmt
at /rustc/90b35a6239c3d8bdabc530a6a0816f7ff89a0aaf/library/core/src/panicking.rs:74:14
2: RustStudy::main
at ./src/main.rs:2:5
3: core::ops::function::FnOnce::call_once
at /Users/stanyin/.rustup/toolchains/stable-aarch64-apple-darwin/lib/rustlib/src/rust/library/core/src/ops/function.rs:250:5
note: Some details are omitted, run with `RUST_BACKTRACE=full` for a verbose backtrace.
In the earlier articles, the program also panicked, but I did not paste the stack backtrace into the article then because we had not covered it yet. What you see above is the complete panic information. Now let’s break it down:
- The first line tells you where the panic occurred — line 2, column 5 of
main.rsin thesrcdirectory. - The second line is the error message defined by the program.
- Starting from the third line, the
stack backtraceis the backtrace information. At the position labeled2ismain.rs. The backtrace contains the list of all functions that were called to reach the place where the error occurred, and below that — at position3— is the code that called our code, which may include Rust’s core library, the standard library, or third-party libraries. - The final
noteline says you can setRUST_BACKTRACEtofullto get all the detailed information. On Windows, typeset RUST_BACKTRACE=full && cargo runin the terminal. On macOS/Linux, typeexport RUST_BACKTRACE=full && cargo run.
To obtain debugging information like this, there is one more prerequisite: the program must be running in debug mode rather than release mode (--release). cargo build and cargo run use debug mode by default, so just make sure not to pass the --release flag.
Top comments (0)