//1. 訪問記憶體衝突
//對同一塊記憶體的讀寫同時進行
//2. 記憶體訪問特徵
//按衝突訪問的語境, 記憶體訪問有三個特徵: 訪問是否是讀或寫, 訪問的中間過程, 記憶體正在被訪問
//特別地, 當兩個訪問滿足以下條件時, 衝突發生:
//至少乙個寫
//訪問記憶體的同乙個位址
//durations 交叉
//讀和寫的區別: 寫改變記憶體位址, 讀不會改變.
//記憶體訪問的 duration 要麼是 instantaneous ,要麼是 long-term
//乙個訪問是 instantaneous 如果在訪問期間其它**不能執行, 因此兩個 instantaneous 訪問不能同時發生, 大多數記憶體訪問都是 instantaneous
func onemore(than number: int) -> int
var mynumber = 1
mynumber = onemore(than: mynumber)
print(mynumber)
// prints "2"
//乙個訪問是 long-term 如果在它訪問開始到訪問結束之前其它**可以執行, 叫做 overlap, 乙個 long-term 訪問可以和其它 long-term 訪問或 instantaneous 訪問 overlap
//overlap 訪問主要發生使用 in-out 引數的函式或方法的**中, 或者結構體的 mutating 方法**中
//3. in-out 引數的衝突訪問
//乙個函式對於所有它的 in-out 引數是 long-term 訪問, 對乙個 in-out 引數的寫訪問在所有的非 in-out 引數被 evaluated 後開始, 並在函式呼叫期間一直持續.如果有多個 in-out 引數, 寫訪問的順序按照引數的順序
//這種 long-term 的寫訪問的後果是你不能訪問被傳遞做為 in-out 引數的原始變數, 即使 scoping rules 和 訪問控制允許, 任何對原始變數的訪問會造成衝突:
var stepsize = 1
func incrementinplace(_ number: inout int)
incrementinplace(&stepsize)
// error: conflicting accesses to stepsize
//number += stepsize, 對 stepsize 是寫
//_ number: inout int, 對 stepsize 是讀
//讀寫訪問同乙個記憶體位址, 並且 overlap, 所以發生衝突
//解決辦法之一是複製乙個 stepsize
var copyofstepsize = stepsize
incrementinplace(©ofstepsize)
// update the original.
stepsize = copyofstepsize
// stepsize is now 2
//讀訪問在寫訪問開始之前結束, 不會發生衝突
//對 in-out 引數 long-term 寫訪問的另乙個後果是, 傳遞同乙個變數給有多個 in-out 引數的函式, 會發生衝突
func balance(_ x: inout int, _ y: inout int)
var playeronescore = 42
var playertwoscore = 30
balance(&playeronescore, &playertwoscore) // ok
// balance(&playeronescore, &playeronescore)
//對同乙個記憶體同時進行讀訪問, 發生衝突
//4. 方法中對 self 的衝突訪問
//乙個struct 的 mutating 方法在方法呼叫期間可以對 self 進行寫訪問.
struct player
}// restorehealth 方法對 self 的寫訪問在方法呼叫期間一直持續, 沒有其它**對 player 例項的屬性 overlap 訪問, 下邊的 sharehealth 方法, 用另乙個 player 例項作為 in-out引數, 提供了 overlap 訪問的可能
// extension player
// }
//// var oscar = player(name: "oscar", health: 10, energy: 10)
// var maria = player(name: "maria", health: 5, energy: 10)
// oscar.sharehealth(with: &maria) // ok: 對 oscar, maria 的讀訪問,訪問 overlap 但是訪問的記憶體位址不同
// oscar.sharehealth(with: &oscar) // error: 對 oscar 同時進行連個讀訪問
// 5. 屬性的衝突訪問
//struct, tuple, enum 等值型別是由個體元素組成, 例如結構體的屬性, 元組的元素.因為它們是值型別, 對其中任何乙個值的改變都會改變整個值, 意味著讀寫乙個屬性要讀寫整個值.例如對乙個元組元素的 overlap 寫訪問會產生衝突:
var playerinformation = (health: 10, energy: 20)
balance(&playerinformation.health, &playerinformation.energy)
// error: conflicting access to properties of playerinformation
//在函式呼叫期間, 元組兩個元素作為 in-out 引數傳入 balance 方法, 同時對整個元組進行寫訪問, 產生衝突
//holly 為全域性變數
var holly = player(name: "holly", health: 10, energy: 10)
balance(&holly.health, &holly.energy) // error
//player 值型別, 同上類似
//實際上, 大多數對 struct 的 overlap 訪問是安全的.例如把上邊的 holly 變數變為乙個區域性的變數
func somefunction()
somefunction()
//排他訪問(exclusive access)是比 memory safety 更嚴格的要求, swift 允許這種 memory-safe 的**, 如果編譯器證明這類 nonexclusive access 是安全的.
//特別地,如果下列條件滿足, 編譯器可以證明對乙個 struct 屬性的訪問是安全的:
//只訪問了儲存屬性, 而沒有訪問計算屬性或型別屬性
//struct 是乙個區域性變數, 不是全域性變數
//struct 沒有被乙個閉包捕獲,或者被非逃逸閉包捕獲
Swift 記憶體安全
swift 也保證同時訪問同一塊記憶體時不會衝突,通過約束 裡對於儲存位址的寫操作,去獲取那一塊記憶體的訪問獨占權。因為 swift 自動管理記憶體,所以大部分時候你完全不需要考慮記憶體訪問的事情。然而,理解潛在的衝突也是很重要的,可以避免你寫出訪問衝突的 如果你的 確實存在衝突,那在編譯時或者執行...
swift 記憶體管理
不管在什麼語言裡,記憶體管理的內容都很重要,所以我打算花上比其他 tip 長一些的篇幅仔細地說說這塊內容。swift 是自動管理記憶體的,這也就是說,我們不再需要操心記憶體的申請和分配。當我們通過初始化建立乙個物件時,swift 會替我們管理和分配記憶體。而釋放的原則遵循了自動引用計數 arc 的規...
Swift 記憶體管理
1 object c 經歷兩個階段 1 手動引用計數記憶體管理 manual reference counting,mrc 2 自動引用計數記憶體管理 automatic refernce counting,arc 2 引用型別 記憶體分配到 堆 上,需要人為管理。值型別 記憶體分配到 棧 上,有處...