Swift 記憶體安全

2021-09-26 03:45:03 字數 2406 閱讀 9265

swift 也保證同時訪問同一塊記憶體時不會衝突,通過約束**裡對於儲存位址的寫操作,去獲取那一塊記憶體的訪問獨占權。

因為 swift 自動管理記憶體,所以大部分時候你完全不需要考慮記憶體訪問的事情。

然而,理解潛在的衝突也是很重要的,可以避免你寫出訪問衝突的**。

如果你的**確實存在衝突,那在編譯時或者執行時就會得到錯誤。

// 向 one 所在的記憶體區域發起一次寫操作

var one =1​

// 向 one 所在的記憶體區域發起一次讀操作

print

("we're number \(one)

!")

注意:

1. 記憶體訪問的衝突會發生在你的**嘗試同時訪問同乙個儲存位址的時侯。

2. 同乙個儲存位址的多個訪問同時發生會造成不可預計或不一致的行為。

3. 在 swift 裡,有很多修改值的行為都會持續好幾行**,在修改值的過程中進行訪問是有可能發生的。

可以思考一下預算表更新的過程,會看到同樣的問題。

更新預算表總共有兩步:首先你把預算項的名字和費用加上,然後再更新總數來反映預算表的現況。

在更新之前和之後,你都可以從預算表裡讀取任何資訊並獲得正確的答案,就像下面展示的那樣。

而當你新增預算項進入表裡的時候,它只是在乙個臨時的,錯誤的狀態,因為總數還沒有被更新。

在新增資料的過程中讀取總數就會讀取到錯誤的資訊。

注意:

1. 如果你寫過併發和多執行緒的**,記憶體訪問衝突也許是同樣的問題。

2. 然而,這裡訪問衝突的討論是在單執行緒的情境下討論的,並沒有使用併發或者多執行緒。

3. 如果你曾經在單執行緒**裡有訪問衝突,swift 可以保證你在編譯或者執行時會得到錯誤。對於多執行緒的**,可以使用 thread sanitizer 去幫助檢測多執行緒的衝突。

特別是,衝突會發生在當你有兩個訪問符合下列的情況:

讀和寫訪問的區別很明顯:

如果乙個訪問不可能在其訪問期間被其它**訪問,那麼就是乙個瞬時訪問。正常來說,兩個瞬時訪問是不可能同時發生的。大多數記憶體訪問都是瞬時的。

例如,下面列舉的所有讀和寫訪問都是瞬時的:

func

onemore

(than number:

int)

->

int​

var mynumber =

1mynumber =

onemore

(than: mynumber)

print

(mynumber)

// 列印「2」

有幾種被稱為長期訪問的記憶體訪問方式,會在別的**執行時持續進行。

瞬時訪問和長期訪問的區別在於別的**有沒有可能在訪問期間同時訪問,也就是在時間線上的重疊。

乙個長期訪問可以被別的長期訪問或瞬時訪問重疊。

var stepsize =1​

func

increment

(_ number:

inout

int)

​increment

(&stepsize)

// 錯誤:stepsize 訪問衝突

在上面的**裡,stepsize 是乙個全域性變數,並且它可以在 increment(_? 裡正常訪問。

然而,對於 stepsize 的讀訪問與 number 的寫訪問重疊了。

func

increment

(_ number :

inout

int)

// 顯式拷貝

var copyofstepsize = stepsize

increment

(©ofstepsize)

​// 更新原來的值

stepsize = copyofstepsize

// stepsize 現在的值是 2

當你在呼叫 increment(_? 之前做乙份拷貝,顯然 copyofstepsize 就會根據當前的 stepsize 增加。讀訪問在寫操作之前就已經結束了,所以不會有衝突。

func

balance

(_ x:

inout

int,

_ y:

inout

int)

{let sum = x + y

x = sum /

2 y = sum -

Swift 記憶體安全

1.訪問記憶體衝突 對同一塊記憶體的讀寫同時進行 2.記憶體訪問特徵 按衝突訪問的語境,記憶體訪問有三個特徵 訪問是否是讀或寫,訪問的中間過程,記憶體正在被訪問 特別地,當兩個訪問滿足以下條件時,衝突發生 至少乙個寫 訪問記憶體的同乙個位址 durations 交叉 讀和寫的區別 寫改變記憶體位址,...

swift 記憶體管理

不管在什麼語言裡,記憶體管理的內容都很重要,所以我打算花上比其他 tip 長一些的篇幅仔細地說說這塊內容。swift 是自動管理記憶體的,這也就是說,我們不再需要操心記憶體的申請和分配。當我們通過初始化建立乙個物件時,swift 會替我們管理和分配記憶體。而釋放的原則遵循了自動引用計數 arc 的規...

Swift 記憶體管理

1 object c 經歷兩個階段 1 手動引用計數記憶體管理 manual reference counting,mrc 2 自動引用計數記憶體管理 automatic refernce counting,arc 2 引用型別 記憶體分配到 堆 上,需要人為管理。值型別 記憶體分配到 棧 上,有處...