iOS底層day1 - 探索一個(gè)NSObject占用多少內(nèi)存

一 、 打印出NSObject的內(nèi)存大小

如圖 :


3496BADC-BAAB-476A-BFC5-A03EFD6F0A24.png

我們可以看到一個(gè)是8個(gè)字節(jié),而另外一個(gè)是16字節(jié),這是為什么呢?接下來我們一步一步探索出結(jié)論。

二、 反編譯出main.cpp

Object-c語言中,我們所編寫的代碼,都是由編譯器編譯,先編譯成c/c++語言,最終再編譯成匯編語言執(zhí)行,要探索一個(gè)NSObject占用多少內(nèi)存,我們就得先反編譯成c/c++代碼

首先,我們?cè)趍ain.m中創(chuàng)建一個(gè)NSObject對(duì)象


0B53E6DA-C352-44D7-A7F4-BD44A081F33A.png

打開終端,目錄切換到main.m下,執(zhí)行

xcrun  -sdk  iphoneos  clang  -arch  arm64  -rewrite-objc main.m -o mian.cpp

生成文件main.cpp


6666EB71-6848-4DAA-B69B-A6B87C663DD6.png

將文件拉入工程中,進(jìn)行進(jìn)一步研究

三 、 了解isa指針

進(jìn)入代碼查看,我們搜索 NSObject_IMPL 會(huì)發(fā)現(xiàn)

6349221E-F9F2-4476-AA0A-734A0B1EB215.png

3D92C009-5217-45BB-9598-D8374238500B.png

里面放著一個(gè) objc_class 的結(jié)構(gòu)體指針 isa,這里我們可以發(fā)現(xiàn)一個(gè)指針在64位系統(tǒng)內(nèi)存中所占的內(nèi)存大小是8個(gè)字節(jié),而我們的NSObject對(duì)象里就只放了這個(gè)isa指針,那么一個(gè)NSObject只占8個(gè)字節(jié)嗎?

四、 探索objc源碼

我們進(jìn)入到蘋果源碼網(wǎng)站 https://opensource.apple.com/tarballs/ 搜索 objc4 發(fā)現(xiàn)

58F57ACB-EB3D-4314-8136-C10338EF185B.png

下載最新源碼 (數(shù)字越大,源碼越新)


4B16BD8E-977C-4F71-B9A5-37118C619E12.png

把源碼導(dǎo)入到我們的工程,我們進(jìn)入之前的 class_getInstanceSize 方法:

D9486424-7E0A-4D73-AF72-15E04CD092BF.png

然后再進(jìn)入 alignedInstanceSize 可以看到:
E892CFDB-9561-4CD4-9CFB-A2149BF8860B.png

我們可以在注釋上看到,class_getInstanceSize方法返回的是成員變量的大小,而在NSObject中 ,只包含了isa指針,所以我們可以知道:class_getInstanceSizeNSObject中,所返回的只是這個(gè)isa指針的大小,而不是NSObject對(duì)象的大小

五、探索對(duì)象所開辟的內(nèi)存大小

我們通過malloc_size所得到的就是NSObject實(shí)際分配的內(nèi)存大小,怎么證明呢?我們知道,iOS中,給一個(gè)對(duì)象分配內(nèi)存都是使用allocWithZone方法,我們進(jìn)入allocWithZone方法:

429C13AF-1FFA-4592-A1BE-0A37CCABA2C6.png

進(jìn)入_objc_rootAllocWithZone :
2A704DEB-8EB9-40C0-9A0C-078047A9CEAC.png

再進(jìn)入:
F9C6886F-86CE-464E-A169-3DC1308A62D7.png

這里,我們可以看到實(shí)際是使用calloc分配內(nèi)存,而傳入的size則是由instanceSize方法獲得,我們進(jìn)入instanceSize查看:

BB5B35A4-3CDC-48C1-9B82-94B3776BE2FB.png

我們可以發(fā)現(xiàn),分配的大小就是alignedInstanceSize + 額外傳入的大小,而且當(dāng)size小于16個(gè)字節(jié)時(shí)自動(dòng)擴(kuò)展到16個(gè)字節(jié),例如:在NSObject中,這里我們的alignedInstanceSize只有isa指針,所以自動(dòng)擴(kuò)展到了16個(gè)字節(jié)。

六、結(jié)論

所以,我們得到結(jié)論,系統(tǒng)給NSObject對(duì)象所分配的內(nèi)存為16個(gè)字節(jié),而NSObject對(duì)象只使用了8個(gè)字節(jié)(在64位下)
class_getInstanceSize方法返回的是這個(gè)對(duì)象需要占用多少空間(結(jié)構(gòu)體內(nèi)存對(duì)齊 - 8的倍數(shù))
malloc_size方法返回的是系統(tǒng)給這個(gè)對(duì)象分配了多少空間 ( iOS系統(tǒng)內(nèi)存對(duì)齊 - 16的倍數(shù) )

特別感謝

@一本大書 提供的底層視頻資源,特發(fā)《中國好室友》獎(jiǎng)狀一份。

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

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