iOS底層原理-alloc、init 探索

本文主要探索alloc的底層實現(xiàn)原理

  • 大家可以通過 Apple source 在 路徑自行下載objc4-781 源碼

首先我們有一個疑問,那就是alloc是如何創(chuàng)建對象,開辟內(nèi)存,并且將對象與內(nèi)存關(guān)聯(lián)起來的呢?我們帶著這些問題打開源碼來一探究竟。

  • 1.首先根據(jù)main函數(shù)中的LGPerson類的alloc方法進入alloc方法的源碼實現(xiàn)(即源碼分析開始)
    image.png

    2.跳轉(zhuǎn)至_objc_rootAlloc底層實現(xiàn)
    image.png

3.跳轉(zhuǎn)至callAlloc

image.png

4.接下來流程會走到callAlloc的具體實現(xiàn)

image.png

5.進入_class_createInstanceFromZone源碼

image.png

這里展示了三個重點方法:
1.cls->instanceSize計算內(nèi)存大小
2.calloc開辟內(nèi)存方式
3.obj->initInstanceIsa isa與類綁定在一起

由此可得出alloc的流程圖如下

image.png
問題一:系統(tǒng)是如何計算內(nèi)存空間大小的,即instanceSize的源碼流程
  • 跳轉(zhuǎn)到instanceSize源碼實現(xiàn)如下圖,流程接下來會走進下圖標識處

    image.png

  • 跳轉(zhuǎn)至函數(shù)fastInstanceSize的源碼實現(xiàn)如圖

    image.png

  • align16源碼實現(xiàn)

    image.png

  • align16算法解讀如下圖:其中x為一個對象,所占內(nèi)存8字節(jié)

    image.png

此算法說明:由此圖看出,與上之后后四位全部抹零了,也就是說保留了16的倍數(shù),16以下全部抹零。由此得出結(jié)論,此算法的目的就是16字節(jié)對齊。

為什么要16字節(jié)對齊?

  • 內(nèi)存對齊是在計算機中排列數(shù)據(jù)、訪問數(shù)據(jù)的一種格式,簡單來說就是前面的地址必須是后面的地址正數(shù)倍,不是就補齊,系統(tǒng)在讀取內(nèi)存的時候,不會隨時改變自己讀取的長度,這么做的目的是為了節(jié)約性能,方便讀取。
  • 首先我們知道任何對象都具備一個isa 的屬性(isa是一個結(jié)構(gòu)體指針占8字節(jié)) ,假設(shè)一個對象沒有屬性,沒有內(nèi)存的情況下,就已經(jīng)占了8字節(jié),如果按照8字節(jié)對齊方式進行存儲時會發(fā)現(xiàn)對象是一個挨著一個的,前一個對象挨著后一個對象isa,這樣就容易導(dǎo)致一些訪問錯誤、野指針的問題出現(xiàn)。為了使整個內(nèi)存更加安全,所以預(yù)留了一些位置。
    到此我們了解了alloc的源碼實現(xiàn),那么init又做了什么呢?

init原理

  • 查看init源碼實現(xiàn)


    image.png

    image.png

說明init只返回了self,什么也沒有做,那么 init 有什么作用呢?
這里是利用了工廠設(shè)計模式, init 的作用是方便子類自定義重寫,預(yù)留自定義內(nèi)容的接口,給子類自由發(fā)揮的空間。比如array和普通的一個對象,初始化之后,所具有的東西是不一樣的,根據(jù)用戶的需要,可以定制化開發(fā)。給開發(fā)人員提供一個構(gòu)造方法的入口。

new

  • 進入new的源碼實現(xiàn)可看到如下圖:


    image.png

newcallAllocinit的結(jié)合,等同于[alloc init],如果子類不想自定義重寫的話,直接可以用new進行初始化開辟內(nèi)存。

最后編輯于
?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請聯(lián)系作者
【社區(qū)內(nèi)容提示】社區(qū)部分內(nèi)容疑似由AI輔助生成,瀏覽時請結(jié)合常識與多方信息審慎甄別。
平臺聲明:文章內(nèi)容(如有圖片或視頻亦包括在內(nèi))由作者上傳并發(fā)布,文章內(nèi)容僅代表作者本人觀點,簡書系信息發(fā)布平臺,僅提供信息存儲服務(wù)。

相關(guān)閱讀更多精彩內(nèi)容

友情鏈接更多精彩內(nèi)容