国产 无码 综合区,色欲AV无码国产永久播放,无码天堂亚洲国产AV,国产日韩欧美女同一区二区

Rust 錯誤處理(上)

這篇具有很好參考價值的文章主要介紹了Rust 錯誤處理(上)。希望對大家有所幫助。如果存在錯誤或未考慮完全的地方,請大家不吝賜教,您也可以點擊"舉報違法"按鈕提交疑問。

目錄

1、用 panic! 處理不可恢復(fù)的錯誤

對應(yīng) panic 時的棧展開或終止

1.1?使用 panic! 的 backtrace

2、用 Result 處理可恢復(fù)的錯誤

2.1?匹配不同的錯誤?

2.2?失敗時 panic 的簡寫:unwrap 和 expect

2.3?傳播錯誤


錯誤是軟件中不可否認的事實,所以 Rust 有一些處理出錯情況的特性。在許多情況下,Rust 要求你承認錯誤的可能性,并在你的代碼編譯前采取一些行動。這一要求使你的程序更加健壯,因為它可以確保你在將代碼部署到生產(chǎn)環(huán)境之前就能發(fā)現(xiàn)錯誤并進行適當(dāng)?shù)奶幚怼?/p>

Rust 將錯誤分為兩大類:可恢復(fù)的recoverable)和?不可恢復(fù)的unrecoverable)錯誤。對于一個可恢復(fù)的錯誤,比如文件未找到的錯誤,我們很可能只想向用戶報告問題并重試操作。不可恢復(fù)的錯誤總是 bug 出現(xiàn)的征兆,比如試圖訪問一個超過數(shù)組末端的位置,因此我們要立即停止程序。

大多數(shù)語言并不區(qū)分這兩種錯誤,并采用類似異常這樣方式統(tǒng)一處理它們。Rust 沒有異常。相反,它有?Result<T, E>?類型,用于處理可恢復(fù)的錯誤,還有?panic!?宏,在程序遇到不可恢復(fù)的錯誤時停止執(zhí)行。本章首先介紹?panic!?調(diào)用,接著會講到如何返回?Result<T, E>。此外,我們將探討在決定是嘗試從錯誤中恢復(fù)還是停止執(zhí)行時的注意事項。

1、用 panic! 處理不可恢復(fù)的錯誤

突然有一天,代碼出問題了,而你對此束手無策。對于這種情況,Rust 有?panic!宏。在實踐中有兩種方法造成 panic:執(zhí)行會造成代碼 panic 的操作(比如訪問超過數(shù)組結(jié)尾的內(nèi)容)或者顯式調(diào)用?panic!?宏。這兩種情況都會使程序 panic。通常情況下這些 panic 會打印出一個錯誤信息,展開并清理棧數(shù)據(jù),然后退出。通過一個環(huán)境變量,你也可以讓 Rust 在 panic 發(fā)生時打印調(diào)用堆棧(call stack)以便于定位 panic 的原因。

對應(yīng) panic 時的棧展開或終止

當(dāng)出現(xiàn) panic 時,程序默認會開始?展開unwinding),這意味著 Rust 會回溯棧并清理它遇到的每一個函數(shù)的數(shù)據(jù),不過這個回溯并清理的過程有很多工作。另一種選擇是直接?終止abort),這會不清理數(shù)據(jù)就退出程序。

那么程序所使用的內(nèi)存需要由操作系統(tǒng)來清理。如果你需要項目的最終二進制文件越小越好,panic 時通過在?Cargo.toml?的?[profile]?部分增加?panic = 'abort',可以由展開切換為終止。例如,如果你想要在 release 模式中 panic 時直接終止:

[profile.release] panic = 'abort'

我們可以再程序中主動拋出一個錯誤,如下圖所示:

fn main() {
    panic!("error error error ...")
}

?運行一下程序,會打印如下信息:

Rust 錯誤處理(上),Rust,rust,開發(fā)語言,后端

通過上圖可以知道:

第一行顯示的是程序代碼發(fā)生錯誤的位置,main.rs 的第二行第五列開始的。

第二行顯示的是panic!里面,我們自定義的錯誤內(nèi)容。

第三行告訴我們可以使用?panic!?被調(diào)用的函數(shù)的 backtrace 來尋找代碼中出問題的地方。

1.1?使用 panic! 的 backtrace

讓我們來看看另一個因為我們代碼中的 bug 引起的別的庫中?panic!?的例子,而不是直接的宏調(diào)用。示例如下所示:

fn main() {
    let arr = [10, 20, 30, 40, 50];
    arr[100];
}

這里嘗試訪問 vector 的第一百個元素(這里的索引是 99 因為索引從 0 開始),不過它只有三個元素。這種情況下 Rust 會 panic。[]?應(yīng)當(dāng)返回一個元素,不過如果傳遞了一個無效索引,就沒有可供 Rust 返回的正確的元素。

C 語言中,嘗試讀取數(shù)據(jù)結(jié)構(gòu)之后的值是未定義行為(undefined behavior)。你會得到任何對應(yīng)數(shù)據(jù)結(jié)構(gòu)中這個元素的內(nèi)存位置的值,甚至是這些內(nèi)存并不屬于這個數(shù)據(jù)結(jié)構(gòu)的情況。這被稱為?緩沖區(qū)溢出buffer overread),并可能會導(dǎo)致安全漏洞,比如攻擊者可以像這樣操作索引來讀取儲存在數(shù)據(jù)結(jié)構(gòu)之后不被允許的數(shù)據(jù)。

為了保護程序遠離這類漏洞,如果嘗試讀取一個索引不存在的元素,Rust 會停止執(zhí)行并拒絕繼續(xù)。嘗試運行上面的程序會出現(xiàn)如下:

Rust 錯誤處理(上),Rust,rust,開發(fā)語言,后端

報錯:運行時遇到panic錯誤,在main.rs第三行第五列開始,索引超過邊界,長度為5,而索引值確實100。

讓我們將?RUST_BACKTRACE?環(huán)境變量設(shè)置為1 的值來獲取 backtrace 看看。

Rust 錯誤處理(上),Rust,rust,開發(fā)語言,后端

這是數(shù)組,報錯比較簡單,如果其他數(shù)據(jù)結(jié)構(gòu)我們可以看一下結(jié)果,例如:string

fn main() {
    let arr = String::from("hello");
    arr[100];
}

?打印結(jié)果如下所示:

Rust 錯誤處理(上),Rust,rust,開發(fā)語言,后端

這里有大量的輸出!你實際看到的輸出可能因不同的操作系統(tǒng)和 Rust 版本而有所不同。為了獲取帶有這些信息的 backtrace,必須啟用 debug 標(biāo)識。當(dāng)不使用?--release?參數(shù)運行 cargo build 或 cargo run 時 debug 標(biāo)識會默認啟用,就像這里一樣。

在上圖中,我們可以看到報錯具體的文件以及對應(yīng)的行號,下面還有rust程序報錯更加詳細的原因,這樣可以更快的為我們解決問題,提升自己的效率。

2、用 Result 處理可恢復(fù)的錯誤

大部分錯誤并沒有嚴(yán)重到需要程序完全停止執(zhí)行。有時候,一個函數(shù)失敗,僅僅就是因為一個容易理解和響應(yīng)的原因。例如,如果因為打開一個并不存在的文件而失敗,此時我們可能想要創(chuàng)建這個文件,而不是終止進程。

Result?枚舉,它定義有如下兩個成員,Ok?和?Err

enum Result<T, E> {
    Ok(T),
    Err(E),
}

T?和?E?是泛型類型參數(shù);現(xiàn)在你需要知道的就是?T?代表成功時返回的?Ok?成員中的數(shù)據(jù)的類型,而?E?代表失敗時返回的?Err?成員中的錯誤的類型。因為?Result?有這些泛型類型參數(shù),我們可以將?Result?類型和標(biāo)準(zhǔn)庫中為其定義的函數(shù)用于很多不同的場景,這些情況中需要返回的成功值和失敗值可能會各不相同。

讓我們調(diào)用一個返回?Result?的函數(shù),因為它可能會失敗:看一下如下示例:

use std::fs::File;
fn main() {
    let file_result = File::open("hello.txt");
}

File::open?的返回值是?Result<T, E>。泛型參數(shù)?T?會被?File::open?的實現(xiàn)放入成功返回值的類型?std::fs::File,這是一個文件句柄。錯誤返回值使用的?E?的類型是?std::io::Error。這些返回類型意味著?File::open?調(diào)用可能成功并返回一個可以讀寫的文件句柄。這個函數(shù)調(diào)用也可能會失?。豪?,也許文件不存在,或者可能沒有權(quán)限訪問這個文件。File::open?函數(shù)需要一個方法在告訴我們成功與否的同時返回文件句柄或者錯誤信息。這些信息正好是?Result?枚舉所代表的。

當(dāng)?File::open?成功時,greeting_file_result?變量將會是一個包含文件句柄的?Ok?實例。當(dāng)失敗時,greeting_file_result?變量將會是一個包含了更多關(guān)于發(fā)生了何種錯誤的信息的?Err?實例。

這里使用match表達式來處理結(jié)果:


fn main() {
    let file_result = File::open("hello.txt");
    let res = match file_result {
        Ok(file) => file,
        Err(err) => panic!("打開文件發(fā)生錯誤...{:?}", err),
    };
}

當(dāng)我們運行以上代碼時,看一下輸出結(jié)果如何:

Rust 錯誤處理(上),Rust,rust,開發(fā)語言,后端

2.1?匹配不同的錯誤?

上面的代碼不管?File::open?是因為什么原因失敗都會?panic!。我們真正希望的是對不同的錯誤原因采取不同的行為:如果?File::open?因為文件不存在而失敗,我們希望創(chuàng)建這個文件并返回新文件的句柄。如果?File::open?因為任何其他原因失敗,例如沒有打開文件的權(quán)限,我們可以通過不同分支把錯誤提示的更加詳細。

fn main() {
    let file_result = File::open("hello.txt");
    match file_result {
        Ok(file) => file,
        Err(err) => match err.kind() {
            ErrorKind::NotFound => match File::create("hello.txt") {
                Ok(file) => file,
                Err(err) => panic!("創(chuàng)建文件失敗 {:?}", err),
            },
            other_error => panic!("其他錯誤 {:?}", other_error),
        },
    };
}

File::open?返回的?Err?成員中的值類型?io::Error,它是一個標(biāo)準(zhǔn)庫中提供的結(jié)構(gòu)體。這個結(jié)構(gòu)體有一個返回?io::ErrorKind?值的?kind?方法可供調(diào)用。io::ErrorKind?是一個標(biāo)準(zhǔn)庫提供的枚舉,它的成員對應(yīng)?io?操作可能導(dǎo)致的不同錯誤類型。我們感興趣的成員是?ErrorKind::NotFound,它代表嘗試打開的文件并不存在。這樣,match?就匹配完?greeting_file_result?了,不過對于?error.kind()?還有一個內(nèi)層?match。

我們希望在內(nèi)層?match?中檢查的條件是?error.kind()?的返回值是否為?ErrorKind的?NotFound?成員。如果是,則嘗試通過?File::create?創(chuàng)建文件。然而因為?File::create?也可能會失敗,還需要增加一個內(nèi)層?match?語句。當(dāng)文件不能被打開,會打印出一個不同的錯誤信息。外層?match?的最后一個分支保持不變,這樣對任何除了文件不存在的錯誤會使程序 panic。

2.2?失敗時 panic 的簡寫:unwrap 和 expect

match?能夠勝任它的工作,不過它可能有點冗長并且不總是能很好的表明其意圖。Result<T, E>?類型定義了很多輔助方法來處理各種情況。其中之一叫做?unwrap,它的實現(xiàn)就像上個示例中的?match?語句。如果?Result?值是成員?Okunwrap?會返回?Ok?中的值。如果?Result?是成員?Err,unwrap?會為我們調(diào)用?panic!。這里是一個實踐?unwrap?的例子:

fn main() {
    let file_result = File::open("hello.txt").unwrap();
}

運行一下這個程序,看下對應(yīng)的輸出:

Rust 錯誤處理(上),Rust,rust,開發(fā)語言,后端

還有另一個類似于?unwrap?的方法它還允許我們選擇?panic!?的錯誤信息:expect。使用?expect?而不是?unwrap?并提供一個好的錯誤信息可以表明你的意圖并更易于追蹤 panic 的根源。expect?的語法看起來像這樣:

fn main() {
    let file_result = File::open("hello.txt").expect("沒有讀取到文件");
}

expect?與?unwrap?的使用方式一樣:返回文件句柄或調(diào)用?panic!?宏。expect?在調(diào)用?panic!?時使用的錯誤信息將是我們傳遞給?expect?的參數(shù),而不像?unwrap?那樣使用默認的?panic!?信息。它看起來像這樣:

Rust 錯誤處理(上),Rust,rust,開發(fā)語言,后端

在生產(chǎn)級別的代碼中,大部分 Rustaceans 選擇?expect?而不是?unwrap?并提供更多關(guān)于為何操作期望是一直成功的上下文。

2.3?傳播錯誤

當(dāng)編寫一個其實先會調(diào)用一些可能會失敗的操作的函數(shù)時,除了在這個函數(shù)中處理錯誤外,還可以選擇讓調(diào)用者知道這個錯誤并決定該如何處理。這被稱為?傳播propagating)錯誤,這樣能更好的控制代碼調(diào)用,因為比起你代碼所擁有的上下文,調(diào)用者可能擁有更多信息或邏輯來決定應(yīng)該如何處理錯誤。

例如,示例 9-6 展示了一個從文件中讀取用戶名的函數(shù)。如果文件不存在或不能讀取,這個函數(shù)會將這些錯誤返回給調(diào)用它的代碼:

fn main() {
    fn read_file() -> Result<String, io::Error> {
        let file_result = File::open("hello.txt");
        let v = String::from("open file success ...");
        match file_result {
            Ok(_) => Ok(v),
            Err(err) => Err(err),
        }
    }
    let res = read_file();
    print!("{:?}", res)
}

這個函數(shù)可以編寫成更加簡短的形式,不過我們以大量手動處理開始以便探索錯誤處理;在最后我們會展示更短的形式。讓我們看看函數(shù)的返回值:Result<String, io::Error>。這意味著函數(shù)返回一個?Result<T, E>?類型的值,其中泛型參數(shù)?T?的具體類型是?String,而?E?的具體類型是?io::Error

如果這個函數(shù)沒有出任何錯誤成功返回,函數(shù)的調(diào)用者會收到一個包含?String?的?Ok?值 —— 函數(shù)從文件中讀取到的用戶名。如果函數(shù)遇到任何錯誤,函數(shù)的調(diào)用者會收到一個?Err?值,它儲存了一個包含更多這個問題相關(guān)信息的?io::Error?實例。文章來源地址http://www.zghlxwxcb.cn/news/detail-801163.html

到了這里,關(guān)于Rust 錯誤處理(上)的文章就介紹完了。如果您還想了解更多內(nèi)容,請在右上角搜索TOY模板網(wǎng)以前的文章或繼續(xù)瀏覽下面的相關(guān)文章,希望大家以后多多支持TOY模板網(wǎng)!

本文來自互聯(lián)網(wǎng)用戶投稿,該文觀點僅代表作者本人,不代表本站立場。本站僅提供信息存儲空間服務(wù),不擁有所有權(quán),不承擔(dān)相關(guān)法律責(zé)任。如若轉(zhuǎn)載,請注明出處: 如若內(nèi)容造成侵權(quán)/違法違規(guī)/事實不符,請點擊違法舉報進行投訴反饋,一經(jīng)查實,立即刪除!

領(lǐng)支付寶紅包贊助服務(wù)器費用

相關(guān)文章

  • Rust錯誤處理

    panic 深入剖析 主動調(diào)用 backtrace 棧展開 panic 時的兩種終止方式 當(dāng)出現(xiàn) panic! 時,程序提供了兩種方式來處理終止流程:棧展開和直接終止 何時該使用 panic! 先來一點背景知識,在前面章節(jié)我們粗略講過 ResultT, E 這個枚舉類型,它是用來表示函數(shù)的返回結(jié)果: 當(dāng)沒有錯誤發(fā)生

    2024年02月06日
    瀏覽(18)
  • 30天拿下Rust之錯誤處理

    30天拿下Rust之錯誤處理

    概述 ????????在軟件開發(fā)領(lǐng)域,對錯誤的妥善處理是保證程序穩(wěn)定性和健壯性的重要環(huán)節(jié)。Rust作為一種系統(tǒng)級編程語言,以其對內(nèi)存安全和所有權(quán)的獨特設(shè)計而著稱,其錯誤處理機制同樣體現(xiàn)了Rust的嚴(yán)謹(jǐn)與實用。在Rust中,錯誤處理通常分為兩大類:不可恢復(fù)的錯誤和可

    2024年03月21日
    瀏覽(20)
  • Rust之構(gòu)建命令行程序(三):重構(gòu)改進模塊化和錯誤處理

    Rust之構(gòu)建命令行程序(三):重構(gòu)改進模塊化和錯誤處理

    Windows 10 Rust 1.74.1 ? VS Code 1.85.1 這次創(chuàng)建了新的工程minigrep. 為了改進我們的程序,我們將修復(fù)與程序結(jié)構(gòu)及其處理潛在錯誤的方式有關(guān)的四個問題。首先,我們的 main 函數(shù)現(xiàn)在執(zhí)行兩項任務(wù):解析參數(shù)和讀取文件。隨著我們程序的增長, main 處理的獨立任務(wù)的數(shù)量也會增加。隨

    2024年01月18日
    瀏覽(106)
  • Rust語言從入門到入坑——(2)Rust在windows上搭建開發(fā)環(huán)境

    Rust語言從入門到入坑——(2)Rust在windows上搭建開發(fā)環(huán)境

    開始搭建一個適合在windows上運行的Rust環(huán)境。 Rust支持的程序語言很多:可詳見官網(wǎng)介紹 本文章主要是在windowns下搭建開發(fā)環(huán)境 首先,需要安裝最新版的 Rust 編譯工具和 Visual Studio Code。 Rust 編譯工具:https://www.rust-lang.org/zh-CN/tools/install Visual Studio Code:https://code.visualstudio.com

    2024年02月09日
    瀏覽(24)
  • Rust軟件外包開發(fā)語言的特點

    Rust軟件外包開發(fā)語言的特點

    Rust 是一種系統(tǒng)級編程語言,強調(diào)性能、安全性和并發(fā)性的編程語言,適用于廣泛的應(yīng)用領(lǐng)域,特別是那些需要高度可靠性和高性能的場景。下面和大家分享 Rust 語言的一些主要特點以及適用的場合,希望對大家有所幫助。北京木奇移動技術(shù)有限公司,專業(yè)的軟件外包開發(fā)公

    2024年02月12日
    瀏覽(23)
  • Rust腐蝕申述教程Rust被辦申述處理

    Rust腐蝕申述教程Rust被辦申述處理

    玩Rust很難避免被辦,但有些被辦是理所當(dāng)。例如:開G、開宏或者其他作弊行為影響了游戲平衡,本指南主要針對綠色玩家被誤封的情況。 一、不同類型的封禁 首先要了解不同的封禁類型,并不是所有的封禁都是公平公正的,特別是國人在外服或者社區(qū)服游戲時經(jīng)常被辦出服

    2024年02月06日
    瀏覽(16)
  • 【rust語言】rust多態(tài)實現(xiàn)方式

    學(xué)習(xí)rust當(dāng)中遇到了這個問題,記錄一下,不對地方望指正 多態(tài)是面向?qū)ο蟪绦蛟O(shè)計中的一個重要概念,指同一個行為或操作在不同實例上具有不同的行為或結(jié)果。簡單來說,多態(tài)就是指同一種類型的對象,在不同的上下文中有不同的行為。多態(tài)性使得程序可以更加靈活、可

    2024年02月11日
    瀏覽(28)
  • C語言和Rust語言的互相調(diào)用(2)(Rust調(diào)用C)

    1.創(chuàng)建項目 rust調(diào)用c方式挺多的,這里采用最通俗易懂的方法,用構(gòu)建腳本進行構(gòu)建整個項目。 2.編輯build.rs的內(nèi)容 這里的build.rs:若要創(chuàng)建構(gòu)建腳本,我們只需在項目的根目錄下添加一個 build.rs 文件即可。這樣一來, Cargo 就會先編譯和執(zhí)行該構(gòu)建腳本,然后再去構(gòu)建整個項

    2024年02月02日
    瀏覽(23)
  • 【Rust 基礎(chǔ)篇】Rust FFI:連接Rust與其他編程語言的橋梁

    Rust是一種以安全性和高效性著稱的系統(tǒng)級編程語言,具有出色的性能和內(nèi)存安全特性。然而,在現(xiàn)實世界中,我們很少有項目是完全用一種編程語言編寫的。通常,我們需要在項目中使用多種編程語言,特別是在與現(xiàn)有代碼庫或底層系統(tǒng)交互時。為了實現(xiàn)跨語言的互操作性,

    2024年02月15日
    瀏覽(29)
  • Rust 筆記:Rust 語言中的常量與變量

    Rust 筆記 Rust 語言中的常量與變量 作者 : 李俊才 (jcLee95):https://blog.csdn.net/qq_28550263?spm=1001.2101.3001.5343 郵箱 : 291148484@163.com 本文地址 :https://blog.csdn.net/qq_28550263/article/details/130875912 【介紹】:本文介紹 Rust 語言中的常量與變量。 上一節(jié):《 上一節(jié)標(biāo)題 》 | 下一節(jié):《

    2024年02月06日
    瀏覽(21)

覺得文章有用就打賞一下文章作者

支付寶掃一掃打賞

博客贊助

微信掃一掃打賞

請作者喝杯咖啡吧~博客贊助

支付寶掃一掃領(lǐng)取紅包,優(yōu)惠每天領(lǐng)

二維碼1

領(lǐng)取紅包

二維碼2

領(lǐng)紅包