關(guān)于rust中的“安全”與“非安全”

在實(shí)際使用Rust過(guò)程中很多時(shí)候沃斤,基于rust自身的來(lái)實(shí)現(xiàn)功能和代碼的編寫蛋铆,并依托編譯期自身來(lái)幫助我們進(jìn)行“編譯檢查”触幼,這時(shí)候相對(duì)來(lái)說(shuō)我們使用的Rust是“安全的”;
不過(guò)另外一些“特殊”場(chǎng)景下的需求需要我們來(lái)處理底層實(shí)現(xiàn)微猖,比如直接與系統(tǒng)層面交互或與匯編指令操作等谈息,那此刻rust可能就變得“不安全”。換種說(shuō)法:rust是一種同時(shí)包含安全和非安全特性的編程語(yǔ)言凛剥。

  • 安全的Rust
    若是我們所編寫的代碼均是使用安全rust進(jìn)行編寫的侠仇,此時(shí)我們無(wú)需擔(dān)心類型安全和內(nèi)存安全,更無(wú)需專注于“垂懸指針”犁珠、“二次釋放引用”逻炊、“其他各種未定義的行為”等;諸如標(biāo)準(zhǔn)庫(kù)中也提供了很多工具庫(kù)犁享,來(lái)幫忙我們構(gòu)建符合安全Rust規(guī)范的高性能的應(yīng)用和庫(kù)余素。

安全的Rust是一種真正安全的編程語(yǔ)言。

  • 非安全的Rust
    在實(shí)際應(yīng)用過(guò)程中炊昆,我們也許會(huì)面臨:編寫一種標(biāo)準(zhǔn)庫(kù)沒(méi)有涉及到的底層抽象桨吊;開發(fā)標(biāo)準(zhǔn)庫(kù)(存粹使用rust);做一些類型系統(tǒng)不能理解的事情凤巨,直接操作各種字節(jié)碼视乐。這時(shí)我們就需要對(duì)底層實(shí)現(xiàn)細(xì)節(jié)的控制-不安全的rust。

不代表Rust不能進(jìn)行“非安全的行為”

  • 安全與不安全的rust的異同
    不過(guò)在Rust中安全和非安全rust的語(yǔ)法規(guī)則是完全相同的敢茁,只不過(guò)非安全的rust允許你可以做一些不安全的行為佑淀;
    另外提供安全與非安全rust的價(jià)值在于既能享用類似C那樣非安全語(yǔ)言的便利及底層的把控,又減少處理C與其他安全語(yǔ)言集成時(shí)的問(wèn)題彰檬;

  • 安全與非安全代碼的交互
    在Rust中安全與非安全代碼是靠unsafe關(guān)鍵字分離的類似兩種語(yǔ)言之間接口的角色伸刃。這也就可以認(rèn)為所有非安全代碼都被unsafe隔離在外面的或者使用#![forbid(unsafe_code)]確保只能編寫安全的代碼。

關(guān)于unsafe

1逢倍、聲明代碼中存在編譯期無(wú)法檢查的安全規(guī)范
2捧颅、開發(fā)者會(huì)自覺遵守相關(guān)規(guī)范并不會(huì)主動(dòng)破壞它(只能默認(rèn)認(rèn)為開發(fā)者“確保”了安全)

在實(shí)際應(yīng)用中我們可以使用unsafe來(lái)定義函數(shù)和trait特型中存在不受編譯期檢查的規(guī)范:

  • 對(duì)于函數(shù)较雕,unsafe意味著調(diào)用函數(shù)的開發(fā)者必須查閱文檔并確保他們的用法符合函數(shù)的安全要求隘道;

當(dāng)給一個(gè)代碼塊添加unsafe關(guān)鍵字,也就是意味著該聲明塊中的代碼都已進(jìn)行“人工檢查”并符合相關(guān)規(guī)范郎笆;

  • 對(duì)于trait的聲明,unsafe意味著trait的開發(fā)者也必須查詢文檔以確保trait的實(shí)現(xiàn)符合其安全要求忘晤;

當(dāng)實(shí)現(xiàn)一個(gè)trait時(shí)使用了unsafe關(guān)鍵字宛蚓,聲明實(shí)現(xiàn)符合trait的安全規(guī)范;比如實(shí)現(xiàn)Send(一個(gè)標(biāo)記trait设塔,只是聲明凄吏;其安全性均有實(shí)現(xiàn)該trait的開發(fā)者者來(lái)“確保”)的類型可以絕對(duì)安全move到另一個(gè)線程中。

3痕钢、標(biāo)準(zhǔn)庫(kù)中的非安全函數(shù)
  • slice::get_unchecked图柏,可接受不受檢查的索引值,也就是存在內(nèi)存安全機(jī)制被破壞的可能;
  • mem::transmute任连,將值重新解析成另一種類型蚤吹,即允許隨意繞過(guò)類型安全機(jī)制的限制;
  • 所有指向確定大小類型 (sized type) 的裸指針都有 offset 方法,當(dāng)傳入的偏移量越界時(shí)將導(dǎo)致未定義行為;
  • 所有 FFI(Foreign Function Interface)函數(shù)都是 unsafe 的随抠,因?yàn)槠渌恼Z(yǔ)言可以做各種的操作而 Rust 編譯器無(wú)法檢查它;
4裁着、非安全的trait
  • Send 是一個(gè)標(biāo)志 trait(即沒(méi)有任何方法的 trait),承諾所有的實(shí)現(xiàn)都可以安全地 move 到另一個(gè)線程;
  • Sync 也是一個(gè)標(biāo)志 trait拱她,承諾線程可以通過(guò)共享的引用共享它的實(shí)現(xiàn);

許多 Rust 標(biāo)準(zhǔn)庫(kù)其實(shí)內(nèi)部也使用了非安全 Rust二驰。這些庫(kù)的實(shí)現(xiàn)方法都經(jīng)過(guò)了嚴(yán)苛的人工檢查,所以這些基于非安全 Rust 實(shí)現(xiàn)的安全 Rust 接口依然可以認(rèn)為是安全的.

安全和非安全的 Rust 之間存在一種不對(duì)稱的信任關(guān)系秉沼。安全 Rust 必須無(wú)條件信任非安全 Rust桶雀,假定所有與之打交道的非安全代碼都是正確的。反過(guò)來(lái)唬复,非安全 Rust 卻要謹(jǐn)慎對(duì)待安全 Rust 的代碼矗积。

非安全 Rust 能做什么

非安全 Rust 比安全 Rust 可以多做的事情只有以下幾個(gè):

  • 解引用裸指針
  • 調(diào)用非安全函數(shù)(包括 C 語(yǔ)言函數(shù),編譯器內(nèi)聯(lián)函數(shù)盅抚,還有直接內(nèi)存分配等)
  • 實(shí)現(xiàn)非安全 trait
  • 訪問(wèn)或修改可變靜態(tài)變量

就這些操作被歸為非安全的漠魏,是因?yàn)槭褂玫貌徽_就會(huì)導(dǎo)致可怕的未定義行為。一旦觸發(fā)了未定義行為妄均,編譯器就可以放飛自我柱锹,肆意破壞你的程序。切記丰包,一定不能給未定義行為任何的機(jī)會(huì)禁熏。

與 C 不同,Rust 充分限制了可能出現(xiàn)的未定義行為的種類邑彪。語(yǔ)言核心只需要防止這幾種行為:

  • 解引用 null 指針瞧毙,懸垂指針,或者未賦值的指針
  • 讀取未初始化的內(nèi)存
  • 破壞指針混淆規(guī)則
  • 創(chuàng)建非法的基本類型:
    • 懸垂引用與 null 引用
    • 空的 fn 指針
    • 0 和 1 以外的 bool 類型值
    • 未定義的枚舉類型的項(xiàng)
    • 在 [0x0,0xD&FF] 和 [0xE000, 0x10FFFF] 以外的 char 類型值
    • 非 utf-8 編碼的 str
  • 不謹(jǐn)慎地調(diào)用其他語(yǔ)言
  • 數(shù)據(jù)競(jìng)爭(zhēng)

只有這些Rust語(yǔ)言自身可以導(dǎo)致未定義行為的操作寄症。當(dāng)然宙彪,非安全函數(shù)和 trait 可以聲明自己專有的安全規(guī)范,要求開發(fā)者必須遵守以避免未定義行為有巧。比如释漆,allocator API 聲明回收一段未分配的內(nèi)存是未定義行為。

但是篮迎,違背這些專有的規(guī)范通常也只是間接地觸發(fā)上面列出的行為男图。另外示姿,編譯器內(nèi)聯(lián)函數(shù)也可能引入一些規(guī)則,一般是針對(duì)代碼優(yōu)化的假設(shè)條件逊笆。比如栈戳,Vec 和 Box 使用的內(nèi)聯(lián)函數(shù)要求傳入的指針永遠(yuǎn)不能為 null。

Rust 對(duì)于一些模糊的操作則通常比較寬容难裆。Rust 會(huì)認(rèn)為下列操作是安全的:

  • 死鎖
  • 競(jìng)爭(zhēng)條件
  • 內(nèi)存泄漏
  • 調(diào)用析構(gòu)函數(shù)失敗
  • 整型值溢出
  • 終止程序
  • 刪除產(chǎn)品數(shù)據(jù)庫(kù)

當(dāng)然子檀,有以上行為的程序極有可能就是錯(cuò)誤的。Rust 提供了一系列的工具減少這種事情的發(fā)生差牛,但是完全地杜絕它們其實(shí)是不現(xiàn)實(shí)的命锄。

引用

meet-safe-and-unsafe

?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請(qǐng)聯(lián)系作者
  • 序言:七十年代末,一起剝皮案震驚了整個(gè)濱河市偏化,隨后出現(xiàn)的幾起案子脐恩,更是在濱河造成了極大的恐慌,老刑警劉巖侦讨,帶你破解...
    沈念sama閱讀 211,743評(píng)論 6 492
  • 序言:濱河連續(xù)發(fā)生了三起死亡事件驶冒,死亡現(xiàn)場(chǎng)離奇詭異,居然都是意外死亡韵卤,警方通過(guò)查閱死者的電腦和手機(jī)骗污,發(fā)現(xiàn)死者居然都...
    沈念sama閱讀 90,296評(píng)論 3 385
  • 文/潘曉璐 我一進(jìn)店門,熙熙樓的掌柜王于貴愁眉苦臉地迎上來(lái)沈条,“玉大人需忿,你說(shuō)我怎么就攤上這事±酰” “怎么了屋厘?”我有些...
    開封第一講書人閱讀 157,285評(píng)論 0 348
  • 文/不壞的土叔 我叫張陵,是天一觀的道長(zhǎng)月而。 經(jīng)常有香客問(wèn)我汗洒,道長(zhǎng),這世上最難降的妖魔是什么父款? 我笑而不...
    開封第一講書人閱讀 56,485評(píng)論 1 283
  • 正文 為了忘掉前任溢谤,我火速辦了婚禮,結(jié)果婚禮上憨攒,老公的妹妹穿的比我還像新娘世杀。我一直安慰自己,他們只是感情好肝集,可當(dāng)我...
    茶點(diǎn)故事閱讀 65,581評(píng)論 6 386
  • 文/花漫 我一把揭開白布玫坛。 她就那樣靜靜地躺著,像睡著了一般包晰。 火紅的嫁衣襯著肌膚如雪湿镀。 梳的紋絲不亂的頭發(fā)上,一...
    開封第一講書人閱讀 49,821評(píng)論 1 290
  • 那天伐憾,我揣著相機(jī)與錄音勉痴,去河邊找鬼。 笑死树肃,一個(gè)胖子當(dāng)著我的面吹牛蒸矛,可吹牛的內(nèi)容都是我干的。 我是一名探鬼主播胸嘴,決...
    沈念sama閱讀 38,960評(píng)論 3 408
  • 文/蒼蘭香墨 我猛地睜開眼雏掠,長(zhǎng)吁一口氣:“原來(lái)是場(chǎng)噩夢(mèng)啊……” “哼!你這毒婦竟也來(lái)了劣像?” 一聲冷哼從身側(cè)響起乡话,我...
    開封第一講書人閱讀 37,719評(píng)論 0 266
  • 序言:老撾萬(wàn)榮一對(duì)情侶失蹤,失蹤者是張志新(化名)和其女友劉穎耳奕,沒(méi)想到半個(gè)月后绑青,有當(dāng)?shù)厝嗽跇淞掷锇l(fā)現(xiàn)了一具尸體,經(jīng)...
    沈念sama閱讀 44,186評(píng)論 1 303
  • 正文 獨(dú)居荒郊野嶺守林人離奇死亡屋群,尸身上長(zhǎng)有42處帶血的膿包…… 初始之章·張勛 以下內(nèi)容為張勛視角 年9月15日...
    茶點(diǎn)故事閱讀 36,516評(píng)論 2 327
  • 正文 我和宋清朗相戀三年闸婴,在試婚紗的時(shí)候發(fā)現(xiàn)自己被綠了。 大學(xué)時(shí)的朋友給我發(fā)了我未婚夫和他白月光在一起吃飯的照片芍躏。...
    茶點(diǎn)故事閱讀 38,650評(píng)論 1 340
  • 序言:一個(gè)原本活蹦亂跳的男人離奇死亡邪乍,死狀恐怖,靈堂內(nèi)的尸體忽然破棺而出对竣,到底是詐尸還是另有隱情庇楞,我是刑警寧澤,帶...
    沈念sama閱讀 34,329評(píng)論 4 330
  • 正文 年R本政府宣布柏肪,位于F島的核電站姐刁,受9級(jí)特大地震影響,放射性物質(zhì)發(fā)生泄漏烦味。R本人自食惡果不足惜聂使,卻給世界環(huán)境...
    茶點(diǎn)故事閱讀 39,936評(píng)論 3 313
  • 文/蒙蒙 一、第九天 我趴在偏房一處隱蔽的房頂上張望谬俄。 院中可真熱鬧柏靶,春花似錦、人聲如沸溃论。這莊子的主人今日做“春日...
    開封第一講書人閱讀 30,757評(píng)論 0 21
  • 文/蒼蘭香墨 我抬頭看了看天上的太陽(yáng)钥勋。三九已至炬转,卻和暖如春辆苔,著一層夾襖步出監(jiān)牢的瞬間,已是汗流浹背扼劈。 一陣腳步聲響...
    開封第一講書人閱讀 31,991評(píng)論 1 266
  • 我被黑心中介騙來(lái)泰國(guó)打工驻啤, 沒(méi)想到剛下飛機(jī)就差點(diǎn)兒被人妖公主榨干…… 1. 我叫王不留,地道東北人荐吵。 一個(gè)月前我還...
    沈念sama閱讀 46,370評(píng)論 2 360
  • 正文 我出身青樓骑冗,卻偏偏與公主長(zhǎng)得像,于是被迫代替她去往敵國(guó)和親先煎。 傳聞我的和親對(duì)象是個(gè)殘疾皇子贼涩,可洞房花燭夜當(dāng)晚...
    茶點(diǎn)故事閱讀 43,527評(píng)論 2 349

推薦閱讀更多精彩內(nèi)容