最近和兩位志同道合的 iOS 發燒友(現在還有人用這詞嗎?)一起開辦了一個針對 iOS 開發者的中文 Podcast,第一集就榮幸地有大師來踢館,因為我們在節目裡提到 Swift 的 value types 都會在 stack 裡,大師 CJ 表示不對喔,若是 reference type 的 value property 或者被 closure 捕獲的 value type 都會在 heap 裡!
這就有趣了不追究不行,但現在還沒有能力看完 Swift run time 的 source code,只好硬著頭皮想了個湊合的辦法來實驗一下。
指向 Class Instance 的 Header Pointer
以前看指標文章時有玩過直接取得位址後,可以對位址內容硬改值以改變本該無法被 mutate 的東西(比如 let )
所以我們先宣告一個 class ,建立一個 instance,我們知道這個 instance 實際上的內容會存在 heap 裡的一塊連續空間裡,然後我們搞一個指向它 instance 開頭的指標:
照理來說這個 instance 裡所有的 property 應該會依著宣告的順序依序擺在這個 headerPointer 指向的位址之後,不過 class 前面有兩個 byte 是用來放 descriptor 以及 retain count,所以 property 會從第三個 byte 開始,我們用 MemoryLayout 來取得各個 property 所佔的空間大小,依序找出 name, age 以及 married 的位址:
這些位址當然還是在 heap 裡,而且應該指到就是這些 value type 的 property 所在地(吧),我們直接強行改變這些位置上的值實驗看看:
OK,我們可以看到值如預料地變化了,這些 value type 真的是在 heap 裡啊!
也用了 Colab 做了一個可以直接在線上 run code 的版本。