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

我們可以看到一個(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ì)象

打開終端,目錄切換到main.m下,執(zhí)行
xcrun -sdk iphoneos clang -arch arm64 -rewrite-objc main.m -o mian.cpp
生成文件main.cpp

將文件拉入工程中,進(jìn)行進(jìn)一步研究
三 、 了解isa指針
進(jìn)入代碼查看,我們搜索 NSObject_IMPL 會(huì)發(fā)現(xiàn)


里面放著一個(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)

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

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

然后再進(jìn)入
alignedInstanceSize 可以看到:
我們可以在注釋上看到,
class_getInstanceSize方法返回的是成員變量的大小,而在NSObject中 ,只包含了isa指針,所以我們可以知道:class_getInstanceSize在NSObject中,所返回的只是這個(gè)isa指針的大小,而不是NSObject對(duì)象的大小
五、探索對(duì)象所開辟的內(nèi)存大小
我們通過malloc_size所得到的就是NSObject實(shí)際分配的內(nèi)存大小,怎么證明呢?我們知道,iOS中,給一個(gè)對(duì)象分配內(nèi)存都是使用allocWithZone方法,我們進(jìn)入allocWithZone方法:

進(jìn)入
_objc_rootAllocWithZone :
再進(jìn)入:

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

我們可以發(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)狀一份。