Overview of t rust error handling
-
Reliability of t rust: error handling
- In most cases: an error is prompted at compile time
-
Wrong classification
-
recoverable
- For example, if the file is not found, try again
-
Unrecoverable
- bug, for example, the index accessed is out of range
-
-
T rust has no exception like mechanism
- Recoverable error, result < T, E >
- Unrecoverable error, panic! macro
Unrecoverable error with panic!
-
When panic! Macro execution:
- Your program will print an error message
- Expand (unwind) and clean up the call stack
- Exit program
-
By default, panic! happen:
-
Program expansion call stack (heavy workload)
- Rust walked back along the call stack
- Clean up the data in each encountered function
-
Or immediately terminate the call stack
- Stop the program directly without cleaning
- The memory needs to be cleaned up by the OS
-
-
To make the binary smaller, change the setting from expand to abort:
- Set the appropriate profile section in Cargo.toml:
- panic = 'abort'
- Set the appropriate profile section in Cargo.toml:
[package] name = "demo" version = "0.1.0" authors = "" edition = "2018" [dependencies] [profile.release] panic = 'abort'
Backtracking information generated using panic
-
panic! May appear in:
- In the code we write
- In the code we rely on
-
You can locate the code causing the problem by calling the backtracking information of the function of panic
-
Backtrace information can be obtained by setting the environment variable RUST_BACKTRACE
-
In order to get backtracking with debug information, the debug symbol (without -- release) must be enabled
Result and recoverable error
Result enumeration
-
enum Result<T, E>{
Ok(T),
Err(E),
}
T: The data type returned in the Ok variant when the operation is successful
E: Type of error returned in Err variant in case of operation failure
use::fs::File; fn main(){ let f = File::open("hello.txt"); }
One way to handle a Result: a match expression
use std::fs::File; fn main() { let f = File::open("hello.txt"); let f = match f { Ok(file) => file, Err(error) => panic!("Problem opening the file: {:?}", error), }; }
Match different errors
use std::fs::File; fn main(){ let f = File::open("hello.txt"); let f = match f{ Ok(file) => file, Err(error) => match error.kind(){ ErrorKind::NotFind => match File::create("hello.txt"){ Ok(fc) => fc, Err(e) => panic!("Error creating file:{:?}", e), }, other_error => panic!("Error opening the file:{:?}", other_errpr), } }; }
Unwrap: a shortcut to match expressions:
-
If the Result is Ok, return the value in Ok
-
If the Result is Err, call the panic! Macro
use std::fs::File; fn main(){ let f = File::open("hello.txt").unwrap(); }
expect: similar to unwrap, but you can specify an error message
use std::fs::File; fn main(){ let f = File::open("hello.txt").expect("File does not exist!"); }
Propagation error
- Processing error in function
- Returns the error to the caller
use std::fs::File; use std::io; use std::io::read; fn read_username_from_file() -> Result<String, io::err> { let f = File::open("hello.txt"); let mut f = match f{ Ok(file) => file, Err(e) => return Err(e), }; let mut s = String::new(); match f.read_to_string(&mut s){ Ok(_) => Ok(s), Err(e) => Err(e), } }
? operator
- ? operator: a shortcut to propagate errors
- If the Result is Ok: the value in Ok is the Result of the expression, and then continue to execute the program
- If the Result is Err: Err is the return value of the whole function, just like using return
use std::fs::File; use std::io; use std::io::Read; fn read_username_from_file() -> Result<String, io::Error> { let f = File::open("hello.txt")?; let mut s = String::new(); f.read_to_string(&mut s)?; Ok(s) }
? and from functions
-
From function on trail STD:: convert:: from:
- Used for conversion between errors
-
When an error is applied, it will be implicitly handled by the from function
-
When? Calls the from function:
-
The error type it receives is converted to the error type defined by the return type of the current function
EA - > EB, EA implements the from function, and the return value is EB
-
-
Used to return the same error type for different error causes
- As long as each error type implements the from function converted to the returned error type
call chaining
use std::fs::File; use std::io; use std::io::Read; fn read_username_from_file() -> Result<String, io::Error> { let mut s = String::new(); File::open("hello.txt")?.read_to_string(&mut s)?; Ok(s) }
The? Operator can only be used for functions with a return value of Result
? operator and main function
- The return type of the main function is: ()
- The return type of the main function can also be: result < T, E >
- Box is a trait object:
- Simple understanding: "any possible error type"
When to use panic!
General principles
- When defining a function that may fail, give priority to returning Result
- Otherwise, return panic!