Swift 中的安全性

做者:Soroush Khanlou,原文連接,原文日期:2017-04-05
譯者:Doye;校對:walkingway;定稿:CMBhtml

Swift 是一門注重安全性的語言,如Swift官網關於頁面中所言git

Swift 是一門通用編程語言,採用現代化的方法來保證安全性與性能,套用軟件設計模式。程序員

還有它的說明github

  • 安全性:那些顯而易見而又便捷的編程方法應該保證是安全的。未定義的行爲會破壞軟件的安全性。在軟件發佈以前就要把開發者的錯誤扼殺在萌芽之中。強調安全性有時會讓你以爲 Swift 語法過於嚴苛,可是它帶來的代碼的明晰從長遠來看仍是利大於弊的。編程

  • 高性能: Swift旨在替代 C 系語言(C,C ++和Objective-C),所以 Swift 必須在絕大多數任務中與這些語言有着接近的性能指數,並且性能須要具備可預測性。並且這種指數須要是一種廣泛的性能指數,而不是曇花一現的僅僅幾種任務類型的高性能。具備各類特性的語言有不少,但仍保持着如此高性能卻實屬罕見。swift

  • 表現力: Swift 受益於計算機科學的幾十年發展,提供了開發人員指望的現代功能並具備有趣的語法。並且 Swift 並不止步於此,Swift 社羣會關注編程語言的發展並取其精華,使得 Swift 一直保持進化,變得更好。設計模式

舉例來講,相似 Optional 這種類型就是 Swift 考慮安全性的一個體現,在其餘的編程語言當中,你並不能知道哪一個變量能夠爲空(null)哪一個不能,而 Optional 攜帶着改變量可能爲空的信息,這就強制開發者去考慮可能爲空的狀況。對於」可空」(nullable)的類型,若是你用強解包符號(!)來處理該類型,有些時候它會直接 crash。Swift 的安全性至關於一條安全帶,你能夠自行解開它,可是風險也要本身來承擔。數組

然而在某些狀況下,安全性看起來並不足夠。好比舉例來講,若是咱們有一個字典,咱們須要經過一些 key 來提取到返回值類型爲 optional 的 value安全

let person: [String: String] = //...
type(of: person["name"]) // => Optional<String>

可是若是咱們對數組進行相似的操做,咱們並不會獲得一個 optional:app

let users: [User] = //...
type(of: users[0]) // => User

緣由是數組可能沒有元素,若是 users 的數組爲空的話,這段程序將會直接crash,從這方面來看,好像Swift並無作到足夠安全。

Swift仍然在開放的演進中,你可能就此問題提些建議到 Swift evolution郵件組
不,那也不會有什麼改變,在 Swift evolution 的 github 庫裏 」常見駁回」提議頁 當中描述了不會接受這項提議:

  • Array< T > 的下標獲取操做不返回一個 T 而是返回一個 T? 或者 T!,當前的數組的邏輯是故意爲之,它準確反映了訪問越界的數組下標是一個邏輯錯誤。若是改變目前的邏輯會下降數組的讀取到一個沒法接受的程度,這項提議提出屢次並不會被社區採納。

這裏指出的緣由是在這種特殊狀況下,性能相當重要。可是若是咱們回過頭來看上面引用的關於頁當中的信息,」安全性」的地位應該是高於」速度」的,難道安全性不該該比速度更爲重要麼?

這裏存在着一個根本的爭議點,在於」安全性」一詞的定義。對於」安全性」一個廣泛的理解是不 crash,而 Swift 核心成員的定義是」永遠不會在無心中訪問錯誤的內存」。

從這點來看,Swift 的下標操做是」安全的」,它永遠都不會去訪問在數組自身分配以外的內存,當你想訪問數組越界的內存時它會當即 crash,如 Optional 類型避免了當前存在的各類空指針引用的 bug 同樣,數組這裏的考慮避免了緩衝區溢出的 bug。

Chris Lattner(Swift 做者)在這段採訪的24.39處有段說明

咱們採用的安全性策略是在綜合的一種妥協。咱們想使Swift成爲一門安全的編程語言,但這種安全並非沒有bug,而是咱們保障內存安全的的基礎上同時提供高性能並且採用一直前進的編程語言範式。

或許,內存安全相對於安全是一個更好的名詞,有些開發者可能更偏向於獲得一個 optional 的返回值,而不是在數組越界訪問的問題裏糾結,每一個人都贊成直接讓程序crash會好過讓程序攜帶着非法的數據繼續運行下去,而這種狀況還可能會被棧溢出的攻擊所利用。

第二種權衡(直接 crash 而不是容許越界訪問)的決定看起來顯而易見,可是有些語言不會作這種保證,在 C 中,訪問越界的數組將會致使未知的行爲(具體取決於使用的編譯器對這種行爲的實現),在 Swift 中開發者會快速的意識到本身犯了相似數組越界的錯誤,Swift團隊以爲這是一個合適的 crash 時機,因此並不會返回一個 optional 甚至是返回一段未知的數據。

使用這裏」安全」的定義也明確了」不安全」的 API 的定義,由於它們直接訪問內存進行編程,程序員們本身必須十分當心保證本身不會訪問到無效的內存,這點尤其困難,即便專家在這種情景也會犯錯,若是對這個主題感興趣去查閱 Matt Gallagher的博客中以安全的方式橋接 C 到 Swift 的相關討論。

Swift 的團隊對於安全的定義可能與你預想的並不徹底一致,可是它們的種種策略確實能夠避免大多數的程序員去考慮各類常見的 bug,將「安全」的定義細化爲「內存安全」可讓我更好的理解 Swift 團隊對於安全的定義。

本文由 SwiftGG 翻譯組翻譯,已經得到做者翻譯受權,最新文章請訪問 http://swift.gg

相關文章
相關標籤/搜索