unsafe
Rust的內存安全依賴於強大的類型系統和編譯時檢測,不過它並不能適應所有的場景。 首先,所有的編程語言都需要跟外部的“不安全”接口打交道,調用外部庫等,在“安全”的Rust下是無法實現的; 其次,“安全”的Rust無法高效表示複雜的數據結構,特別是數據結構內部有各種指針互相引用的時候;再次, 事實上還存在著一些操作,這些操作是安全的,但不能通過編譯器的驗證。
因此在安全的Rust背後,還需要unsafe的支持。
unsafe塊能允許程序員做的額外事情有:
- 解引用一個裸指針
*const T和*mut T 
#![allow(unused)] fn main() { let x = 5; let raw = &x as *const i32; let points_at = unsafe { *raw }; println!("raw points at {}", points_at); }
- 讀寫一個可變的靜態變量
static mut 
#![allow(unused)] fn main() { static mut N: i32 = 5; unsafe { N += 1; println!("N: {}", N); } }
- 調用一個不安全函數
 
unsafe fn foo() { //實現 } fn main() { unsafe { foo(); } }
使用unsafe
unsafe fn不安全函數標示如果調用它可能會違反Rust的內存安全語意:
#![allow(unused)] fn main() { unsafe fn danger_will_robinson() { // 實現 } }
unsafe block不安全塊可以在其中調用不安全的代碼:
#![allow(unused)] fn main() { unsafe { // 實現 } }
unsafe trait不安全trait及它們的實現,所有實現它們的具體類型有可能是不安全的:
#![allow(unused)] fn main() { unsafe trait Scary { } unsafe impl Scary for i32 {} }
safe != no bug
對於Rust來說禁止你做任何不安全的事是它的本職,不過有些是編寫代碼時的bug,它們並不屬於“內存安全”的範疇:
- 死鎖
 - 內存或其他資源溢出
 - 退出未調用析構函數
 - 整型溢出
 
使用unsafe時需要注意一些特殊情形:
- 數據競爭
 - 解引用空裸指針和懸垂裸指針
 - 讀取未初始化的內存
 - 使用裸指針打破指針重疊規則
 &mut T和&T遵循LLVM範圍的noalias模型,除了如果&T包含一個UnsafeCell<U>的話。不安全代碼必須不能違反這些重疊(aliasing)保證- 不使用
UnsafeCell<U>改變一個不可變值/引用 - 通過編譯器固有功能調用未定義行為:
- 使用
std::ptr::offset(offset功能)來索引超過對象邊界的值,除了允許的末位超出一個字節 - 在重疊(overlapping)緩衝區上使用
std::ptr::copy_nonoverlapping_memory(memcpy32/memcpy64功能) 
 - 使用
 - 原生類型的無效值,即使是在私有字段/本地變量中:
- 空/懸垂引用或裝箱
 bool中一個不是false(0)或true(1)的值enum中一個並不包含在類型定義中判別式char中一個代理字(surrogate)或超過char::MAX的值str中非UTF-8字節序列
 - 在外部代碼中使用Rust或在Rust中使用外部語言