In addition to Weibo, there is also WeChat
Please pay attention
WeChat public account
Shulou
2025-01-16 Update From: SLTechnology News&Howtos shulou NAV: SLTechnology News&Howtos > Development >
Share
Shulou(Shulou.com)06/03 Report--
This article mainly introduces "what are Rust error handling". In daily operation, I believe many people have doubts about Rust error handling. The editor consulted all kinds of materials and sorted out simple and easy-to-use operation methods. I hope it will be helpful for you to answer the doubts about "Rust error handling". Next, please follow the editor to study!
Error handling is a very important aspect of programming languages. At present, the ways of error handling can be divided into two categories, the first is the error handling scheme based on return value led by C language, and the second is the error handling scheme based on exception led by Java language. It can also be classified according to whether the error is recoverable, for example, the C language will use the error code to return the value for the recoverable error, and exit will be called directly to exit the program for the unrecoverable error; the exception system of Java is divided into Exception and Error, corresponding to recoverable error and unrecoverable error respectively. In Rust, the error handling scheme is similar to C language, but it is more perfect and easy to use: for unrecoverable errors, use panic to deal with, so that the program can exit directly and output relevant information; for recoverable errors, use Option and Result to encapsulate the return value, which makes it more expressive.
Introduction to unrecoverable error panic
For unrecoverable errors, Rust provides a panic mechanism to make the program crash quickly and report the corresponding error message. The general scenario of panic is that if execution continues, there will be extremely serious memory security problems, and at this time, the harm caused by the continued execution of the program is more serious than the crash. For example:
Fn main () {let v = vec! [1,2,3]; println! ("{:?}", v [6]);}
For the above program, the array v has three elements, but the index value is 6, so the program crashes after running and reports the following error:
Thread 'main' panicked at' index out of bounds: the len is 3 but the index is 6 layers, src/main.rs:176:22stack backtrace: function call stack... panic implementation mechanism
In Rust, there are two ways to implement panic:
Unwind mode: when panic occurs, it exits the function call stack layer by layer, and the local variables in the stack can be destructed normally.
Abort mode: when panic occurs, exit the whole program directly.
By default, the compiler uses unwind mode, and the function call stack information can help us quickly locate the first site where panic occurs; but some embedded systems can only choose abort mode because of lack of resources, which can be specified through rustc-C panic=abort test.rs mode.
In Rust, the internal implementation of panic through unwind is basically the same as the exception of C++. Rust provides some utility functions that allow users to terminate stack expansion in code like the try-catch mechanism, such as:
Fn main () {std::panic::catch_unwind (| {let v = vec! [1,2,3]; println! ("{:?}", v [6]); println! ("interrupted"); / / No output}) .ok (); println! ("continue"); / / normal output}
When you run the program, you can find that the println! ("interrupted"); statement is not executed, so the panic is started in the previous statement, and the function call stack is destroyed, but std::panic::catch_unwind prevents the call stack from continuing to expand, so println! ("continue"); executes normally.
It should be noted that do not use catch_unwind for process control like try-catch, Rust recommends error handling mechanism based on return value, because since panic occurs, it is better to let the program crash as soon as possible, which is conducive to debugging bug, while the use of catch_unwind will temporarily suppress errors, thus allowing errors to be transmitted to other locations, resulting in not easy to find the first site of the program crash. Catch_unwind is mainly used in the following two situations:
In the FFI scenario, if the C language calls the function of Rust, a panic appears inside the Rust. If the panic is not handled properly within the Rust, it will be thrown into the C code, resulting in "undefined behavior".
Some advanced abstraction mechanisms, such as thread pooling, need to prevent stack unfolding. If there is a panic in a thread, we just want to shut down the thread instead of dragging the entire thread pool down.
Recoverable error basic error handling
For recoverable errors, a return value-based scheme is provided in Rust, mainly based on Option and Result types. Option indicates that the return value is either empty or non-empty, and Result represents either the normal value or the wrong value. They are defined as follows:
Pub enum Option {/ No value None, / / Some value `T` Some (# [stable (feature = "rust1", since = "1.0.0")] T),} pub enum Result {/ Contains the success value Ok (# [stable (feature = "rust1", since = "1.0.0")] T), / / Contains the error value Err (# [stable (feature = "rust1", since = "1.0.0")] E),}
Let's look at a typical use of Result in a standard library. The from_str method in FromStr can construct an instance of the current type from a string, but the construction may fail. This trait is implemented for the bool type in the standard library. A value of type bool is returned in normal cases, and a value of type ParseBoolError is returned in case of exception:
Pub trait FromStr: Sized {/ The associated error which can be returned from parsing. Type Err; fn from_str (s: & str)-> Result;} impl FromStr for bool {type Err = ParseBoolError; fn from_str (s: & str)-> Result {match s {"true" = > Ok (true), "false" = > Ok (false), _ = > Err (ParseBoolError {_ priv: ()),}
Let's take a look at the typical use of Option in a standard library. The next method of Iterator either returns the next element or has no element to return, so using Option is very appropriate.
# [must_use = "iterators are lazy and do nothing unless consumed"] pub trait Iterator {type Item; fn next (& mut self)-> Option;...}
The Option type solves the null pointer problem in many programming languages. The design of null pointers was not carefully thought out when added to the programming language, but simply because it was easy to implement. The biggest problem with null pointers is that they violate the rules of the type system. The type specifies the range of possible values for the data, the possible operations on these values, the meaning that the data represents, and how the data is stored. However, an ordinary pointer and a null pointer, even if they are of the same type, get different results by doing the same operation. Therefore, it cannot be said that null pointers and ordinary pointers are of the same type. Null pointers open a gap in the type system and introduce a value that must be specially handled at run time, which makes compiler type checking meaningless here. In response, Rust's solution is to raise the null pointer null from a value to a type, using the None of Option of type enum to represent a null pointer, while enum in Rust requires that every possibility of enum must be dealt with when used, thus forcing programmers to consider the case where Option is None. A similar design has also been added to CCompact +, but it can not be enforced due to forward compatibility problems, so its role is weakened a lot.
Question mark operator
Question mark operator is provided in Rust? Syntax sugar to simplify the use of Result and Option, the question mark operator means that if the result is Err, it is returned early, otherwise execution continues. ? Corresponding to the trait of std::ops::Try, the compiler will put expr? This expression is automatically converted to the following semantics:
Match Try::into_result (expr) {Ok (V) = > v, Err (e) = > return Try::from_error (From::from (e)),}
Try has been implemented for Result and Option types in the standard library:
Impl ops::Try for Option {type Ok = T; type Error = NoneError; fn into_result (self)-> Result {self.ok_or (NoneError)} fn from_ok (v: t)-> Self {Some (v)} fn from_error (_: NoneError)-> Self {None} impl ops::Try for Option {type Ok = T; type Error = NoneError Fn into_result (self)-> Result {self.ok_or (NoneError)} fn from_ok (v: t)-> Self {Some (v)} fn from_error (_: NoneError)-> Self {None}}
As you can see, for Result types, when the question mark operator is executed, if Err is encountered, Fromtrait is called for type conversion, and then interrupts the current logic to return ahead of time.
It should be noted that the introduction of the question mark operator brings challenges to the main function, because the question mark operator requires the function to return a value of type Result, while the main function is of type fn ()-> (). The solution to this problem is to change the signature type of the main function, but this will break the old code. Rust's ultimate solution is to introduce a trait:
Pub trait Termination {/ Is called to get the representation of the value as status code. / This status code is returned to the operating system. Fn report (self)-> i32 } impl Termination for () {# [inline] fn report (self)-> i32 {ExitCode::SUCCESS.report ()}} impl Termination for Result {fn report (self)-> i32 {match self {Ok (()) = > () .report (), Err (err) = > Err:: (err). Report () } impl Termination for! {fn report (self)-> i32 {self}} impl Termination for Result {fn report (self)-> i32 {let Err (err) = self Eprintln! ("Error: {:?}", err); ExitCode::FAILURE.report ()} impl Termination for ExitCode {# [inline] fn report (self)-> i32 {self.0.as_i32 ()}}
The signature of the main function is correspondingly changed to fn ()-> T, and the standard library implements this trait for the Result type, () type, and so on, so that these types can be used as return types of the main function.
At this point, the study of "what is the error handling of Rust" is over. I hope to be able to solve your doubts. The collocation of theory and practice can better help you learn, go and try it! If you want to continue to learn more related knowledge, please continue to follow the website, the editor will continue to work hard to bring you more practical articles!
Welcome to subscribe "Shulou Technology Information " to get latest news, interesting things and hot topics in the IT industry, and controls the hottest and latest Internet news, technology news and IT industry trends.
Views: 0
*The comments in the above article only represent the author's personal views and do not represent the views and positions of this website. If you have more insights, please feel free to contribute and share.
Continue with the installation of the previous hadoop.First, install zookooper1. Decompress zookoope
"Every 5-10 years, there's a rare product, a really special, very unusual product that's the most un
© 2024 shulou.com SLNews company. All rights reserved.