iOS底層原理之一:一個NSObject對象占多大內(nèi)存

題記

這系列的目的是回顧一下學(xué)到的知識,對OC底層原理作一翻探究,以及對一些常見的底層原理面試題作一次總結(jié)。

準(zhǔn)備工作


  • 如題目所示,我們新建一個demo來探究:一個NSObject對象占多大內(nèi)存


如大部分iOS開發(fā)者所知,OC的底層是C/C++,為了清楚了解NSObject的本質(zhì),我們可以看看底層是怎么實現(xiàn)。

  • 進(jìn)入mian.m文件所在的路徑,打開terminal
  • 輸入以下指令把OC代碼轉(zhuǎn)成C++(因為mac平臺下使用的是arm64架構(gòu),實際情況可以選擇相應(yīng)的架構(gòu))
xcrun -sdk iphoneos clang -arch arm64 -rewrite-objc main.m -o main-arm64.cpp 
  • 我們可以得到一個main-arm64.cpp 文件


  • 把cpp文件直接拽入Xcode,為了不顯示報錯信息,我們不讓它參與編譯


探究


  • 點擊NSObject我們可以看到OC的定義


  • 在main.cpp文件里面搜索NSObject_IMPL,我們可以看到NSObject轉(zhuǎn)成C++后的本質(zhì)是一個結(jié)構(gòu)體


  • 我們再點擊Class進(jìn)去,可以看到其實它就是一個指針。那么我們知道在64位環(huán)境下,它占8個字節(jié)。


論證


  • 有了這個推論,我們還可以進(jìn)一步論證我們的觀點,這里我們用到runtime,也就是運行時的一個方法class_getInstanceSize
  • 為了驗證推論的準(zhǔn)確性,我們先找到蘋果開源的源碼,打開瀏覽器http://opensource.apple.com/tarballs/搜索`objc
  • 點擊進(jìn)去,我們找到數(shù)字最大的一個,一般來說也是最新的一個


  • 下載壓縮包解壓后并打開


  • 搜索class_getInstanceSize,并在.mm文件里面可以看到它的實現(xiàn)
  • 點擊3中的alignedInstanceSize()方法,我們可以看到進(jìn)一步注釋,這個方法返回的是類對象成員變量所占用的內(nèi)存大小


  • 所以通過調(diào)用runtime的這個方法我們可以看到,NSObject類對象所占用的內(nèi)存大小為8個字節(jié)


疑問


  • 這個就是最終結(jié)果了嗎?不用急著下定義。我們還有個叫malloc_size的方法可以查看系統(tǒng)分配內(nèi)存的大小。由于這里需要傳一個C的指針,所以我們打印obj的時候需要橋接一下。然后我們會發(fā)現(xiàn),返回的大小是16而不是8!


總結(jié)


  • 為什么會造成這個不一致呢?我們還是要從源碼入手分析,首先還是在objc的源碼里面搜索allocWithZone這個方法,查看創(chuàng)建一個對象是內(nèi)存是怎么分配


  • 我們點擊進(jìn)入class_createInstance這個方法,看到返回的是_class_createInstanceFromZone方法,我們再次點擊進(jìn)去就能很快鎖定我們需要的信息:size
  • 我們可以從注釋看到,所有對象至少分配16 bytes 的大小,從方法實現(xiàn)來看,如果size < 16,則size = 16



所以我們可以很好的回答這個問題,系統(tǒng)分配了16個字節(jié)空間給NSObject對象,但是在64位環(huán)境下,NSObject只使用了8個字節(jié)。

最后編輯于
?著作權(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)容