原始指針

2018-08-12 22:03 更新

原始指針

Rust 在標(biāo)準(zhǔn)庫有許多不同的智能指針類型,但是有兩種特別的類型。Rust 的安全來自于編譯時檢查,但原始指針沒有這樣的保證,使用起來不安全?!   ?/p>

*const T 和 *mut T 在 Rust 中被稱為“原始指針”。有時,當(dāng)寫庫的某些類型時,出于某種原因你需要繞過 Rust 的安全保證。在這種情況下,你可以使用原始指針來實現(xiàn)你的庫,同時為給用戶一個安全接口。例如,允許 * 指針起別名,允許他們被用來寫共享類型,甚至線程安全共享內(nèi)存類型( Rc和 Arc 類型在 Rust 中都被完全實現(xiàn))。

這里要記住原始指針與其他指針類型是不同的地方。他們:

  • 不能保證指有效內(nèi)存,甚至不保證非空(不像 Box 和 & );  
  • 不像 Box ,沒有任何自動清理功能,所以需要手動管理資源;   
  • 是原始舊數(shù)據(jù),也就是說,他們不轉(zhuǎn)移指向,不像 Box ,因此 Rust 編譯器不能防止像 use-after-free 一樣的漏洞;   
  • 與 & 不用,缺乏任何形式的生命周期,所以編譯器無法推斷懸空指針;  
  • 不能保證別名使用或者易變性,不同于直接通過 *const T 不能產(chǎn)生變化。

Basics

創(chuàng)建一個原始指針是絕對安全的:

let x = 5;
let raw = &x as *const i32;

let mut y = 10;
let raw_mut = &mut y as *mut i32;

然而,非關(guān)聯(lián)化的指針是不安全的。這是行不通的:

let x = 5;
let raw = &x as *const i32;

println!("raw points at {}", *raw);

它會給出這樣的錯誤:

error: dereference of unsafe pointer requires unsafe function or block [E0133]
 println!("raw points at{}", *raw);
 ^~~~

原始指針廢棄時,你承擔(dān)這樣的后果,那就是它不指向那個正確的地方。因此,你需要 unsafe:

let x = 5;
let raw = &x as *const i32;

let points_at = unsafe { *raw };

println!("raw points at {}", points_at);

要了解更多關(guān)于原指針的操作,請看 API 文檔。

FFI

對 FFI 來說原指針是很有用的:Rust 的 *const T 和 *mut T 與 C 的 const T 和 T 是相似的。更多關(guān)于它的使用,請看 FFI 章節(jié)。

引用和原始指針

在運行時,一個原始指針 * 和一個指向同一塊數(shù)據(jù)的引用具有相同的表示。事實上,一個 &T 引用將隱式強制轉(zhuǎn)換為安全代碼中的 *const T 原始指針并且與常量 mut 相似(兩種強制轉(zhuǎn)換可以顯式地被執(zhí)行,值分別是 const T 和 mut T)?!   ?/p>

相反,從 const 指向引用 & 是不安全的。 &T 總是有效的,因此至少,原始指針 const T 必須指向一個 T 類型的有效實例。此外,由此產(chǎn)生的指針必須滿足引用的別名使用和可變性規(guī)則。編譯器假定這些屬性對任何引用都是真的,不管他們是如何創(chuàng)建的,因此任何從原始指針的轉(zhuǎn)換都認為它們有這些屬性。程序員必須保證這一點?!   ?/p>

推薦的轉(zhuǎn)換方法是

let i: u32 = 1;

// explicit cast
let p_imm: *const u32 = &i as *const u32;
let mut m: u32 = 2;

// implicit coercion
let p_mut: *mut u32 = &mut m;

unsafe {
let ref_imm: &u32 = &*p_imm;
let ref_mut: &mut u32 = &mut *p_mut;
}

&*x 解除引用要使用 transmute。transmute 是非常強大的,更受限制的操作也能正確使用;例如,它要求 x 是一個指針(而不像 transmute)。

以上內(nèi)容是否對您有幫助:
在線筆記
App下載
App下載

掃描二維碼

下載編程獅App

公眾號
微信公眾號

編程獅公眾號