鍍金池/ 教程/ Java/ unsafe
標(biāo)準(zhǔn)輸入與輸出
消息傳遞
循環(huán)
注釋
Rust for Mac OS
幾種智能指針
Cell, RefCell
trait對(duì)象 (trait object)
rust web 開(kāi)發(fā)
Unsafe、原始指針
Macro
迭代器
函數(shù)
Borrow, BorrowMut, ToOwned
快速上手
二叉樹(shù)
編輯器
測(cè)試與評(píng)測(cè)
Deref
安裝Rust
哈希表 HashMap
原生類(lèi)型
17.錯(cuò)誤處理
VS Code 安裝配置
動(dòng)態(tài)數(shù)組Vec
模式匹配
操作符和格式化字符串
Rust for Linux
函數(shù)參數(shù)
Visual Studio
vim/GVim安裝配置
閉包作為參數(shù)和返回值
安全(Safety)
Cow
生命周期( Lifetime )
閉包的實(shí)現(xiàn)
所有權(quán)(Ownership)
Atom
將Rust編譯成庫(kù)
類(lèi)型、運(yùn)算符和字符串
類(lèi)型系統(tǒng)中的幾個(gè)常見(jiàn) trait
特性
屬性和編譯器參數(shù)
Spacemacs
集合類(lèi)型
Rust json處理
Heap & Stack
并行
標(biāo)準(zhǔn)庫(kù)示例
基本程序結(jié)構(gòu)
鏈表
trait 和 trait對(duì)象
前期準(zhǔn)備
代碼風(fēng)格
編譯器參數(shù)
基于語(yǔ)義化版本的項(xiàng)目版本聲明與管理
Rust 版本管理工具: rustup
引用&借用(References&Borrowing)
注釋與文檔
10.1 trait關(guān)鍵字
模式
調(diào)用ffi函數(shù)
unsafe
并發(fā),并行,多線(xiàn)程編程
AsRef 和 AsMut
Rust旅程
Rust for Windows
結(jié)構(gòu)體與枚舉
條件分支
附錄I-術(shù)語(yǔ)表
變量綁定與原生類(lèi)型
Mutex 與 RwLock
泛型
裸指針
常用數(shù)據(jù)結(jié)構(gòu)實(shí)現(xiàn)
系統(tǒng)命令:調(diào)用grep
Into/From 及其在 String 和 &str 互轉(zhuǎn)上的應(yīng)用
共享內(nèi)存
Sublime
網(wǎng)絡(luò)模塊:W貓的回音
函數(shù)返回值
包和模塊
高階函數(shù)
函數(shù)與方法
match關(guān)鍵字
隊(duì)列
目錄操作:簡(jiǎn)單grep
語(yǔ)句和表達(dá)式
并發(fā)編程
閉包
測(cè)試
閉包的語(yǔ)法
同步
迭代器
String
Send 和 Sync
Rc 和 Arc
屬性
Emacs
優(yōu)先隊(duì)列
Prelude
cargo簡(jiǎn)介
控制流(control flow)
數(shù)組、動(dòng)態(tài)數(shù)組和字符串
FFI
模塊和包系統(tǒng)、Prelude
實(shí)戰(zhàn)篇
Rust 是一門(mén)系統(tǒng)級(jí)編程語(yǔ)言,被設(shè)計(jì)為保證內(nèi)存和線(xiàn)程安全,并防止段錯(cuò)誤。作為系統(tǒng)級(jí)編程語(yǔ)言,它的基本理念是 “零開(kāi)銷(xiāo)抽象”。理
運(yùn)算符重載
Any和反射
rust數(shù)據(jù)庫(kù)操作
輸入輸出流
復(fù)合類(lèi)型
性能測(cè)試

unsafe

Rust的內(nèi)存安全依賴(lài)于強(qiáng)大的類(lèi)型系統(tǒng)和編譯時(shí)檢測(cè),不過(guò)它并不能適應(yīng)所有的場(chǎng)景。 首先,所有的編程語(yǔ)言都需要跟外部的“不安全”接口打交道,調(diào)用外部庫(kù)等,在“安全”的Rust下是無(wú)法實(shí)現(xiàn)的; 其次,“安全”的Rust無(wú)法高效表示復(fù)雜的數(shù)據(jù)結(jié)構(gòu),特別是數(shù)據(jù)結(jié)構(gòu)內(nèi)部有各種指針互相引用的時(shí)候;再次, 事實(shí)上還存在著一些操作,這些操作是安全的,但不能通過(guò)編譯器的驗(yàn)證。

因此在安全的Rust背后,還需要unsafe的支持。

unsafe塊能允許程序員做的額外事情有:

  • 解引用一個(gè)裸指針*const T*mut T
let x = 5;
let raw = &x as *const i32;
let points_at = unsafe { *raw };
println!("raw points at {}", points_at);
  • 讀寫(xiě)一個(gè)可變的靜態(tài)變量static mut
static mut N: i32 = 5;
unsafe {
    N += 1;
    println!("N: {}", N);
}
  • 調(diào)用一個(gè)不安全函數(shù)
unsafe fn foo() {
    //實(shí)現(xiàn)
}
fn main() {
    unsafe {
        foo();
    }
}

使用unsafe

unsafe fn不安全函數(shù)標(biāo)示如果調(diào)用它可能會(huì)違反Rust的內(nèi)存安全語(yǔ)意:

unsafe fn danger_will_robinson() {
    // 實(shí)現(xiàn)
}

unsafe block不安全塊可以在其中調(diào)用不安全的代碼:

unsafe {
    // 實(shí)現(xiàn)
}

unsafe trait不安全trait及它們的實(shí)現(xiàn),所有實(shí)現(xiàn)它們的具體類(lèi)型有可能是不安全的:

unsafe trait Scary { }
unsafe impl Scary for i32 {}

safe != no bug

對(duì)于Rust來(lái)說(shuō)禁止你做任何不安全的事是它的本職,不過(guò)有些是編寫(xiě)代碼時(shí)的bug,它們并不屬于“內(nèi)存安全”的范疇:

  • 死鎖
  • 內(nèi)存或其他資源溢出
  • 退出未調(diào)用析構(gòu)函數(shù)
  • 整型溢出

使用unsafe時(shí)需要注意一些特殊情形:

  • 數(shù)據(jù)競(jìng)爭(zhēng)
  • 解引用空裸指針和懸垂裸指針
  • 讀取未初始化的內(nèi)存
  • 使用裸指針打破指針重疊規(guī)則
  • &mut T&T遵循LLVM范圍的noalias模型,除了如果&T包含一個(gè)UnsafeCell<U>的話(huà)。不安全代碼必須不能違反這些重疊(aliasing)保證
  • 不使用UnsafeCell<U>改變一個(gè)不可變值/引用
  • 通過(guò)編譯器固有功能調(diào)用未定義行為:
    • 使用std::ptr::offset(offset功能)來(lái)索引超過(guò)對(duì)象邊界的值,除了允許的末位超出一個(gè)字節(jié)
    • 在重疊(overlapping)緩沖區(qū)上使用std::ptr::copy_nonoverlapping_memory(memcpy32/memcpy64功能)
  • 原生類(lèi)型的無(wú)效值,即使是在私有字段/本地變量中:
    • 空/懸垂引用或裝箱
    • bool中一個(gè)不是false(0)或true(1)的值
    • enum中一個(gè)并不包含在類(lèi)型定義中判別式
    • char中一個(gè)代理字(surrogate)或超過(guò)char::MAX的值
    • str中非UTF-8字節(jié)序列
  • 在外部代碼中使用Rust或在Rust中使用外部語(yǔ)言