9.1無法恢復的錯誤與 panic!

無法恢復的錯誤與 panic!

有時你的代碼中會發生嚴重問題,而你無能為力。在這些情況下,Rust 提供了 panic! 宏。實際上,有兩種方式會導致 panic:一種是執行某個操作使代碼產生 panic(例如訪問數組越界),另一種是顯式調用 panic! 宏。無論哪種情況,都會在程序中引發 panic。默認情況下,這些 panic 會打印失敗信息、展開棧幀、清理堆棧并退出程序。通過設置環境變量,你還可以讓 Rust 在發生 panic 時顯示調用棧,以便更容易定位問題源頭。

響應 Panic 的棧展開或終止

默認情況下,當發生 panic 時,程序開始進行棧展開,也就是 Rust 會沿著調用鏈向上回溯,并清理每個函數中的數據。然而,回溯和清理工作量較大。因此,Rust 允許你選擇立即終止程序作為替代方案,即不進行任何清理直接結束運行。

此時程序占用的內存將由操作系統負責回收。如果你的項目需要盡可能減小生成的二進制文件體積,可以通過在 Cargo.toml 文件相應的 [profile] 部分添加 panic = 'abort' 來切換為遇到 panic 時直接終止。例如,如果想要在發布模式下遇到panic就終止,可以這樣寫:

[profile.release]
panic = 'abort'

下面我們嘗試在一個簡單程序中調用 panic!

文件名:src/main.rs

fn main() {panic!("crash and burn");
}

運行該程序,會看到類似如下輸出:

$ cargo runCompiling panic v0.1.0 (file:///projects/panic)Finished `dev` profile [unoptimized + debuginfo] target(s) in 0.25sRunning `target/debug/panic`thread 'main' panicked at src/main.rs:2:5:
crash and burn
note: run with `RUST_BACKTRACE=1` environment variable to display a backtrace

panic! 的調用導致最后兩行顯示錯誤信息。第一行展示了我們的panic消息以及出錯位置:src/main.rs:2:5 表示這是 src/main.rs 文件第 2 行,第 5 個字符處。

這里指示的位置屬于我們的代碼,如果跳轉至該行,就能看到觸發宏調用的那條語句。但有時候,panic! 調用可能是在被我們代碼間接調用的其他庫代碼里,此時錯誤消息報告的是那個庫文件及其對應行號,而非最終導致該宏被觸發的我們自己的源碼位置。

我們可以利用產生這個panic!調用函數鏈上的回溯來找出引起問題的具體部分。為了理解如何使用這種backtrace,我們來看另一個例子,當因為我們的bug而從庫內部觸發了一個panic!而不是直接從自己代碼里調動宏時,會是什么樣子。列表9-1包含了一段嘗試訪問 vector 中超出有效索引范圍元素的代碼示例。

這里,我們試圖訪問向量的第100個元素(索引為99,因為索引從0開始),但該向量只有三個元素。在這種情況下,Rust 會發生 panic。使用 [] 應該返回一個元素,但如果傳入了無效的索引,Rust 無法返回正確的元素。在 C 語言中,嘗試讀取數據結構末尾之外的數據是未定義行為。你可能會得到內存中對應那個位置的數據,即使那塊內存不屬于該數據結構。這被稱為緩沖區溢出讀取,如果攻擊者能夠操縱索引以讀取他們不應該訪問的數據,就可能導致安全漏洞。為了保護程序免受此類漏洞影響,如果你嘗試讀取不存在的索引處的元素,Rust 會停止執行并拒絕繼續運行。我們來試試看:

$ cargo run
Compiling panic v0.1.0 (file:///projects/panic)
Finished `dev` profile [unoptimized + debuginfo] target(s) in 0.27s
Running `target/debug/panic`
thread 'main' panicked at src/main.rs:4:6: index out of bounds: the len is 3 but the index is 99
note: run with `RUST_BACKTRACE=1` environment variable to display a backtrace

這個錯誤指向 main.rs 的第4行,我們在這里嘗試訪問向量 v 中的索引99。
note 行告訴我們可以設置 RUST_BACKTRACE 環境變量來獲取導致錯誤發生時的回溯信息。回溯是一系列調用函數列表,用于追蹤到達當前點所經過的所有函數調用。Rust 中的回溯與其他語言類似:閱讀回溯時應從頂部開始,一直讀到看到自己編寫文件的位置,那就是問題起源所在的位置。上方代碼是你的代碼調用過的,下方代碼則是調用你的代碼。這些上下文可能包括 Rust 核心代碼、標準庫或你使用的一些 crate。
讓我們通過將 RUST_BACKTRACE 環境變量設置為非零值來獲取回溯,如下所示:

$ RUST_BACKTRACE=1 cargo run
thread 'main' panicked at src/main.rs:4:6: index out of bounds: the len is 3 but the index is 99
stack backtrace:
0: rust_begin_unwind at /rustc/4d91de4e48198da2e33413efdcd9cd2cc0c46688/library/std/src/panicking.rs:692:5
1: core::panicking::panic_fmt at /rustc/4d91de4e48198da2e33413efdcd9cd2cc0c46688/library/core/src/panicking.rs:75:14
2: core::panicking::panic_bounds_check at /rustc/4d91de4e48198da2e33413efdcd9cd2cc0c46688/library/core/src/panicking.rs:273:5
3:<usize as core::slice::index::SliceIndex<[T]>>::index at file:///home/.rustup/toolchains/1.85/lib/rustlib/src/rust/library/core/src/slice/index.rs :274 :10
4:core :: slice :: index::<impl core :: ops :: index :: Index<I> for [T]>::index 在 file:///home/.rustup/toolchains/1.85/lib/rustlib/src/rust/library/core/src/slice/index .rs :16 :9
...
note:部分細節已省略,可通過設置 `RUST_BACKTRACE=full` 獲取詳細完整回溯。

清單9-2:當環境變量 RUST_BACKTRACE 設置后,由 panic! 調用生成并顯示出的回溯信息
輸出內容非常多!具體輸出可能因操作系統和 Rust版本不同而異。要獲得帶有這些信息的回溯,需要啟用調試符號。當使用 cargo build 或 cargo run 且未加 --release 標志時,會默認啟用調試符號,這正是我們的情況。
在清單9-2中的輸出里,第6行指向項目中導致問題的位置——src/main.rs 文件第4行。如果不希望程序 panic,應從第一條提及自己編寫文件路徑的信息開始調查。在清單9-1中,我們故意寫了會觸發 panic 的代碼,要修復它,只需避免請求超出向量范圍之外的元素即可。當未來你的代碼出現 panic 時,你需要弄明白是什么操作、什么數值導致了 panic,以及應該如何改正這段邏輯。
我們將在“是否應該使用 panic!”章節中進一步討論何時以及為何應或不應使用 panic! 來處理錯誤情況。

本文來自互聯網用戶投稿,該文觀點僅代表作者本人,不代表本站立場。本站僅提供信息存儲空間服務,不擁有所有權,不承擔相關法律責任。
如若轉載,請注明出處:http://www.pswp.cn/news/917255.shtml
繁體地址,請注明出處:http://hk.pswp.cn/news/917255.shtml
英文地址,請注明出處:http://en.pswp.cn/news/917255.shtml

如若內容造成侵權/違法違規/事實不符,請聯系多彩編程網進行投訴反饋email:809451989@qq.com,一經查實,立即刪除!

相關文章

分享低功耗單火線開關語音識別方案

在眾多老舊建筑和常規家居環境里&#xff0c;單火線布線是主流方式。單火線語音識別芯片方案通過研發和應用特殊的單火線語音識別芯片&#xff0c;實現設備在單火線供電條件下穩定運行&#xff0c;并精準識別語音指令&#xff0c;為智能家居、智能照明等領域帶來便捷的語音控制…

如何在Windows操作系統上通過conda 安裝 MDAnalysis

MDAnalysis 是一個開源的 Python 庫,旨在提供一個高效且靈活的方式來分析和處理分子動力學(MD)模擬數據。它可以從不同的文件格式中讀取模擬軌跡和結構數據,進行復雜的數據處理和分析,廣泛應用于生物物理學、化學、材料科學等領域。 一、創建虛擬環境 為了能夠順利安裝,減…

實用PDF演示解決方案

它打破了傳統閱 讀模式&#xff0c;讓PDF文檔也能像PPT一樣流暢播放&#xff0c;特別適合匯報、講解等展示場景。它是綠色單文件版&#xff0c;無需安裝&#xff0c;雙擊紅色圖標即點即用。運行后第一件事&#xff0c;建議把界面語言切換成中文&#xff0c;操作更順手。導入PDF…

VS Code中如何關閉Github Copilot

點擊頂部搜索欄后面的Copilot圖標&#xff0c;在下拉菜單中選擇Hide Copilot。在彈出的提示框中&#xff0c;點擊Hide Copilot按鈕就可以了。

MySQL學習從零開始--第六部分

Binlog是什么&#xff1f;有哪幾種格式&#xff1f;推薦使用哪種&#xff0c;為什么 Binlog是什么 Binlog二進制日志是MySQL Server層記錄所有更改數據庫內容的操作日志的二進制文件&#xff0c;如操作UPDATE,DELETE,INSERTBinlog不記錄SELECT&#xff0c;SHOW等查詢操作使主從…

走進computed,了解computed的前世今生

computed&#xff08;計算屬性&#xff09;并不是vue獨創的&#xff0c;而是源自計算機科學和響應式編程的長期發展 計算理論的奠基&#xff1a; 函數式編程的純函數思想&#xff1a;計算屬性的核心特征&#xff08;無副作用、依賴輸入確定輸出&#xff09;直接來源于函數式編程…

Java 23 新特性解析與代碼示例

Java 23 新特性解析與代碼示例 文章目錄Java 23 新特性解析與代碼示例1. 引言2. 正式特性2.1. Markdown文檔注釋 (JEP 467)2.2. 廢棄sun.misc.Unsafe的內存訪問方法以移除 (JEP 471)2.3. ZGC&#xff1a;默認啟用代際模式 (JEP 474)3. 預覽特性3.1. 原始類型在模式、instanceof…

spring boot + mybatis + mysql 只有一個實體類的demo

使用MyBatis進行數據庫操作&#xff0c;配置簡單。主要演示了mybatis可以不用只使用方法名來對應mapper.java和mapper.xml。 目錄結構 pom.xml src/ ├── main/ │ ├── java/ │ │ └── com/ │ │ └── springbootjdbcweb/ │ │ └── …

iRemovalPro完美繞iCloud插卡打電話,A12+支持iOS 18.1.1

iRemovalPro 專業工具全解析與操作指南 &#xff08;支持iOS 14.0 - 16.6.1&#xff0c;A7-A15芯片設備&#xff09; &#x1f449;下載地址見文末 iRemoval Pro iRemoval 專業版是一款來自外國安全研究員的工具&#xff0c;用來幫助一些人因為忘記自己的ID或者密碼&#xff0c…

安卓SELinux策略語法

目錄前言一、 通用AV規則語法1.1 allow source target:class permissions;1.2 neverallow source target:class permissions;二、type三、attribute四、typeattribute五、alias六、typealias七、init_daemon_domain7.1 init_daemon_domain 宏概述7.2 宏展開與實現7.2.1 展開后規…

vscode cursor配置php的debug,docker里面debug

VSCode PHP調試配置指南 概述 本文介紹如何在VSCode中配置PHP調試環境&#xff0c;包括本地和Docker環境。 前置要求 VSCodePHP 7.0Xdebug擴展PHP Debug VSCode擴展 本地調試配置 1. 安裝Xdebug # Ubuntu/Debian sudo apt-get install php-xdebug# MacOS brew install p…

elk部署加日志收集

清華大學鏡像源地址&#xff1a;Index of /elasticstack/8.x/yum/8.13.2/ | 清華大學開源軟件鏡像站 | Tsinghua Open Source Mirror 一、elasticsearch 1.安裝 rpm -ivh elastic-agent-8.13.2-x86_64.rpm 2.修改配置 vim /etc/elasticsearch/elasticsearch.yml 修改如下&…

dify 升級1.7.1 插件無法下載依賴

dify 升級1.7.1 插件無法下載依賴 1. 安裝通義千問插件&#xff0c;各種報錯&#xff1b; 使用下面命令查看docker 鏡像日志 docker logs -f --tail100 docker-plugin_daemon-1 2025/08/01 07:42:21 full_duplex.go:59: [INFO]init environment for plugin langgenius/tongyi…

linux中簡易云盤系統項目實戰:基于 TCP協議的 Socket 通信、json數據交換、MD5文件區別與多用戶文件管理實現

&#x1f4cb; 項目介紹 本項目是一個基于Linux環境的簡易云盤系統&#xff0c;采用C/S&#xff08;客戶端/服務器&#xff09;架構&#xff0c;實現了類似百度網盤的基本功能。系統通過TCP Socket進行網絡通信&#xff0c;使用JSON格式進行數據交換&#xff0c;利用SQLite3數據…

linux中posix消息隊列的使用記錄

在linux中使用posix中的消息隊列時遇到了一個問題&#xff0c;就是在發送消息時&#xff0c;如果隊列滿了&#xff0c;mq_send接口會一直阻塞&#xff0c;經過查找資料后才發現&#xff0c;該接口默認是阻塞的&#xff0c;也就是說&#xff0c;當隊列滿了以后&#xff0c;接口會…

01 基于sklearn的機械學習-機械學習的分類、sklearn的安裝、sklearn數據集及數據集的劃分、特征工程(特征提取與無量綱化、特征降維)

文章目錄機械學習機械學習分類1. 監督學習2. 半監督學習3. 無監督學習4. 強化學習機械學習的項目開發步驟scikit-learn1 scikit-learn安裝2 sklearn數據集1. sklearn 玩具數據集鳶尾花數據集糖尿病數據集葡萄酒數據集2. sklearn現實世界數據集20 新聞組數據集3. 數據集的劃分特…

n8n】n8n的基礎概念

以下是為初學者整理的 n8n 基本概念總結&#xff0c;幫助快速理解核心功能和使用邏輯&#xff1a;1. 工作流&#xff08;Workflow&#xff09;核心單元&#xff1a;n8n的一切操作基于工作流&#xff0c;代表一個自動化流程。組成&#xff1a;由多個節點&#xff08;Nodes&#…

機器學習基礎-matplotlib

一、相關知識點二、plotfrom pylab import mpl # 設置顯示中文字體 mpl.rcParams["font.sans-serif"] ["SimHei"] # 設置正常顯示符號 mpl.rcParams["axes.unicode_minus"] False #%%#%% import matplotlib.pyplot as plt import random# 畫出…

spring-ai-alibaba 學習(十九)——graph之條件邊、并行節點、子圖節點

前面了解了基礎的概念及流程&#xff0c;以及一些參數類下面了解一些特殊的邊和節點條件邊常見的流程圖可能長這個樣子&#xff1a;其中菱形的為條件節點&#xff08;或者叫判定節點&#xff09;&#xff0c;但是在spring-ai-alibaba-graph中&#xff0c;并沒有條件節點在sprin…

深入淺出設計模式——創建型模式之原型模式 Prototype

文章目錄原型模式簡介原型模式結構關于克隆方法&#xff1a;淺拷貝/深拷貝原型模式代碼實例定義原型類和克隆方法客戶端使用代碼示例示例一&#xff1a;淺拷貝示例二&#xff1a;深拷貝原型模式總結開閉原則代碼倉庫原型模式&#xff1a;用原型實例指定創建對象的種類&#xff…