Rust āā A language empowering everyone to build reliable and efficient software.
Lec03: Error Handling
Ownership
Example One:
| |
The problem is in the first f(s), main has give s ās ownership to f, and f doesnāt give it back. So main lose s ās ownership in the second f(s). By the way, after the first f(s) ends, s will be free.
šExceptionļ¼
| |
It works fine because u32 implements a ācopy traitā that changes what happens when it is assigned to variables or passed as a parameter.
Good news, only primitive types + a handful of others use copy semantics, and you just need to remember those.
Example Two:
| |
It works fine, because s s1 s2 are all immutable.
Remember, you can have as many read-only pointers to something as you want, as long as no one can change what is being pointed to.
šĀ Counter Example One:
| |
This fails to compile becauseĀ sĀ is immutable, and on the next line, we try to borrow aĀ mutableĀ reference toĀ s. If this were allowed, we could modify the string usingĀ s1, even though it was supposed to be immutable.
šĀ Counter Example Two:
| |
This fails again, but for a different reason.
- We first declareĀ
sĀ as mutable. š - We borrow a mutable reference toĀ
s. š - We try to borrow an immutable reference toĀ
s. However, there already exists a mutable reference toĀs. Rust doesnāt allow multiple references to exist when a mutable reference has been borrowed. Otherwise, the mutable reference could be used to change (potentially reallocate) memory when code using the other references least expect it.
šĀ Counter Example Three:
| |
- We first declareĀ
sĀ as mutable. š - We borrow a mutable reference toĀ
s. š - We try to useĀ
s. However, the value has been āborrowed outā toĀs1Ā and hasnāt been āreturnedā yet. As such, we canāt useĀs1.
Example Three:
| |
It works fine.
šĀ Thinking
āOne thing thatās confusing is why sometimes I need to &var and other times I can just use var: for example, set.contains(&var), but set.insert(var) ā why?"
Answer:
When inserting an item into a set, we want to transfer ownership of that item into the set; that way, the item will exist as long as the set exists. (It would be bad if you added a string to the set, and then someone freed the string while it was still a member of the set.) However, when trying to see if the set contains an item, we want to retain ownership, so we only pass a reference.
Error Handling about null pointer
Introduce Option<T> in Rust
Null pointer is dangerous in C/C++. To solve this problem, we might want some way to indicate to the compiler when a valueĀ mightĀ beĀ NULL, so that the compiler can then ensure code using those values is equipped to handleĀ NULL.
Rust does this with theĀ OptionĀ type. A value of typeĀ Option<T>Ā can either beĀ NoneĀ orĀ Some(value of type T).
Definition of Option<T>:
| |
Example:
| |
Handling errors
Introduce Result<T, E> in Rust
- C has an absolutely garbage system for handling errors.
- C++ and many other languages use exceptions to manage error conditions. It works well, but also has many disadvantages
- failure modes are hard to spot
Rust takes a different, two-pronged approach to error handling
- unrecoverable error, use
panic!
| |
Panics terminate the program immediately and cannot be caught.
(Side note: itās technically possible to catch and recover from panics, but doing so really defeats the philosophy of error handling in Rust, so itās not advised.)
- recoverable error
You should return aĀ Result. If you returnĀ Result<T, E>, you can either returnĀ Ok(value of type T)Ā orĀ Err(value of type E)
| |
Or you could use unwrap instead
| |
If theĀ ResultĀ wasĀ Ok,Ā unwrap()Ā returns the success value; otherwise, it causes a panic.Ā
expect()Ā does the same thing, but prints the supplied error message when it panics
Written by Jiacheng Hu, at Zhejiang University, Hangzhou, China.
