Swift 5將帶來改進的Swift程序內存安全性,在程序的其他部分修改變量時,不允許通過其他變量名來訪問這些變量。這個變更對現有應用程序的行為和Swift編譯器本身都有重要影響。
Swift 5將帶來改進的Swift程序內存安全性,在程序的其他部分修改變量時,不允許通過其他變量名來訪問這些變量。這個變更對現有應用程序的行為和Swift編譯器本身都有重要影響。
在多種情況下會發生獨占內存訪問問題。編譯器可以靜態地捕獲大部分問題,剩下的只能在運行時處理。只能在運行時處理的問題包括具有轉義閉包、類類型屬性、靜態屬性和全局變量的排他性違規。
為了更好地說明這個問題,我們可以考慮一個相當普遍的情況:修改一個函數的inout變量,這個函數執行了一個閉包,這個閉包使用同一作用域內的兩個不同的名稱訪問上述的變量:
func modifyTwice(_ value: inout Int, by modifier: (inout Int) -\u0026gt; ()) { modifier(\u0026amp;value) modifier(\u0026amp;value)}func testCount() { var count = 1 modifyTwice(\u0026amp;count) { $0 += count } print(count)}
在這個例子中,因為使用count同時作為modifyTwice和modifier的inout參數,所以出現了問題。我們不清楚print語句應該打印出什么內容。第一次count變量遞增,它的值遞增到2。但是,當執行第二次加法時,要添加到$0的count值是多少?這可能取決于很多因素,因為內存操作不一定是瞬時的。更糟糕的是,編譯器可能會引入優化,進一步使這種情況復雜化。
這個問題不僅與通過不同變量名同時修改內存的不可預測性有關,也與編譯器的復雜性有關。
這可能會導致意外和混亂的結果。它還導致編譯器和標準庫的實現具有很大的保守性,它們通常必須確保程序的基本可靠性(沒有崩潰或未定義的行為),即使是在不尋常的情況下。
所有這些意味著如果發現獨占訪問沖突,使用Swift 5編譯器編譯的應用程序將在運行時崩潰。這個行為以前在Swift 4編譯器調試模式下可用,因此,僅在運行時模式下測試過的程序在使用Swift 5編譯時有崩潰的風險。
Swift 4編譯器可用,因此僅在運行時模式下測試的程序在使用Swift 5編譯時可能會崩潰。
修復訪問獨占違規的一般方法是復制數據。在我們的示例中,這將歸結為:
func modifyTwice(_ value: inout Int, by modifier: (inout Int) -\u0026gt; ()) { modifier(\u0026amp;value) modifier(\u0026amp;value)}func testCount() { var count = 1 let increment = count modifyTwice(\u0026amp;count) { $0 += increment } print(count)}
實際上,訪問獨占違規檢查可能會被禁用,但強烈建議不要這樣做:
雖然禁用運行時檢查可能可以解決性能問題,但這并不意味著獨占違規是安全的。如果沒有啟用強制執行,程序員必須遵守獨占規則。
查看英文原文:
https://www.infoq.com/news/2019/02/swift-5-exclusive-memory-access