OC對象的本質(zhì)--一個NSObject占用多少內(nèi)存?

問題:一個NSObject占用多少內(nèi)存?

首先我們創(chuàng)建一個NSObject對象

NSObject *obj = [[NSObject alloc] init];

其實這個問題想問的就是obj這個對象所指的指針占用的內(nèi)存大小追驴。
如果我們想要搞清楚obj對象所指指針的大小械哟,那么我們只要搞清楚NSObjcet在內(nèi)存的布局及其底層相關(guān)的知識。

  • 其實我們平時編寫的Objective-C代碼殿雪,底層實現(xiàn)其實都是C/C++代碼
    OC代碼的實現(xiàn)
  • 所以OC的面向?qū)ο蠖际腔?code>C/C++的數(shù)據(jù)結(jié)構(gòu)實現(xiàn)的

說到這里暇咆,們我們來思考一個問題,Objective-C的對象和類丙曙,主要基于C/C++的什么數(shù)據(jù)結(jié)構(gòu)實現(xiàn)的呢爸业?

由于oc的類和對象可能包含很多種屬性如下代碼

{
    int _age;
    double _height;
    NSString *_name;
}

所以根據(jù)上面的不同數(shù)據(jù)類型的屬性來猜測,那就是結(jié)構(gòu)體亏镰。

  • OC代碼轉(zhuǎn)化成C/C++代碼

那么我們就把OC代碼嘗試著轉(zhuǎn)化成C/C++代碼扯旷,來看一下到底是不是結(jié)構(gòu)體。

打開終端拆挥,將`OC `代碼轉(zhuǎn)化成`C/C++`
xcrun -sdk iphoneos clang -arch arm64 -rewrite-objc  OC源文件 -o 輸出的cpp文件

那么根據(jù)上面的終端指令薄霜,我們將OCmain.m文件轉(zhuǎn)化成C/C++main.cpp文件,具體指令

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

指令輸入完成后回車纸兔,生成如下main.cpp文件

cpp文件

  • NSObject內(nèi)存本質(zhì)

將上一步的C++代碼打開我們可以看一下NSObject內(nèi)存本質(zhì)到底是什么樣子的

struct NSObject_IMPL {
    Class isa;
};

有上面的代碼可以看出來惰瓜,NSObject對象在內(nèi)存中就是一個結(jié)構(gòu)體
而其里面的Class isa,點進去我們可以看到他的定義

typedef struct objc_class *Class;

實際上,isa就是一個指向結(jié)構(gòu)體的指針汉矿。
那么既然isa是個指針崎坊,那么他在64位的環(huán)境下占8個字節(jié),在32環(huán)境上占4個字節(jié)洲拇。(我們所使用的是64位架構(gòu)的)
因為這個結(jié)構(gòu)體就isa1個成員奈揍,假設(shè)isa的地址是0x100400b70,那么這個結(jié)構(gòu)體的地址就應(yīng)該是isa的地址赋续。所以obj的地址應(yīng)該就是結(jié)構(gòu)體的地址男翰,這個地址占用的內(nèi)存大小就是結(jié)構(gòu)體的大小,即isa的大小纽乱,isa這個地址所占用的內(nèi)存大小為8個字節(jié)蛾绎,那么NSObject對象在內(nèi)存中所占用的大小也應(yīng)該是8個字。這些就是NSObject內(nèi)存本質(zhì)鸦列。

  • 解決最上面的問題

根據(jù)上面NSObject內(nèi)存本質(zhì)的分析租冠,我們應(yīng)該會認(rèn)為NSObject對象在內(nèi)存中占用了8個字節(jié),那么實際上并不是薯嗤,而是16個字節(jié)顽爹,為什么呢?讓我們來進一步分析:在runtime中有個class_getInstanceSize方法獲取實例的大小骆姐,首先導(dǎo)入頭文件#import <objc/runtime.h>镜粤,那么我們來打印一下看看

NSObject *obj = [[NSObject alloc] init];
NSLog(@"class_getInstanceSize--%zd", class_getInstanceSize([NSObject class]));

輸出結(jié)果為:

interview-OC對象的本質(zhì)[10809:700450] class_getInstanceSize--8

還有一個獲取內(nèi)存大小的方法捏题,導(dǎo)入頭文件#import <malloc/malloc.h>

NSObject *obj = [[NSObject alloc] init];
NSLog(@"malloc_size--%zd", malloc_size((__bridge const void *)obj));

輸出結(jié)果為:

interview-OC對象的本質(zhì)[10809:700450] malloc_size--16

根據(jù)上面的兩個方法獲取的內(nèi)存大小不一樣,class_getInstanceSize獲取的大小為8個字節(jié)繁仁,malloc_size獲取的大小是16個字節(jié)涉馅。為什么會出現(xiàn)兩種不同的情況呢,不要著急黄虱,我們來進一步分析
我們可以去runtime的源碼里面稚矿,看一下class_getInstanceSize具體是怎么實現(xiàn)的。OC所有開放的源碼地址https://opensource.apple.com/tarballs
我們找到runtime源碼位置然后下載下來

runtime源碼

點進去然后下載數(shù)字最大的捻浦。
下載完成晤揣,打開項目,然后找到class_getInstanceSize的實現(xiàn)
class_getInstanceSize實現(xiàn)

然后我們點擊去看下alignedInstanceSize實現(xiàn)

   // Class's ivar size rounded up to a pointer-size boundary.
    uint32_t alignedInstanceSize() {
        return word_align(unalignedInstanceSize());
    }

可以從注釋上看出來返回的是Class's ivar size,類的成員變量的大小朱灿,
因為NSObject對象只有一個isa成員變量昧识,因為返回的是8個字節(jié)

我們還可以從源碼的另外一個角度來分析一下,看一下alloc的時候分配了多大的內(nèi)存大小盗扒,我們還是搜索剛才的源碼allocWithZone然后找到_objc_rootAllocWithZone在這個方法中返回的是class_createInstance(cls, 0)跪楞,然后跳轉(zhuǎn)進去,返回值再點擊去可以看到instanceSize侣灶,再點進去可以看到如下的代碼

size_t instanceSize(size_t extraBytes) {
        size_t size = alignedInstanceSize() + extraBytes;
        // CF requires all objects be at least 16 bytes.
        if (size < 16) size = 16;
        return size;
    }

從上述代碼注釋中可以看到甸祭,CF要求至少得返回16個字節(jié)的內(nèi)存大小。

  • 最終的答案

從上面的所有分析來看褥影,我們很容易能回答出文中最開始提出的問題

一個NSObject占用多少內(nèi)存池户?
答:
1、系統(tǒng)分配了16個字節(jié)給NSObject對象(可以通過malloc_size函數(shù)得到)
2凡怎、但NSObject對象內(nèi)部只使用了8個字節(jié)空間(在64bit環(huán)境下校焦,可以通過class_getInstanceSize函數(shù)獲得)

最后編輯于
?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請聯(lián)系作者
  • 序言:七十年代末,一起剝皮案震驚了整個濱河市统倒,隨后出現(xiàn)的幾起案子寨典,更是在濱河造成了極大的恐慌,老刑警劉巖房匆,帶你破解...
    沈念sama閱讀 206,378評論 6 481
  • 序言:濱河連續(xù)發(fā)生了三起死亡事件凝赛,死亡現(xiàn)場離奇詭異,居然都是意外死亡坛缕,警方通過查閱死者的電腦和手機,發(fā)現(xiàn)死者居然都...
    沈念sama閱讀 88,356評論 2 382
  • 文/潘曉璐 我一進店門捆昏,熙熙樓的掌柜王于貴愁眉苦臉地迎上來赚楚,“玉大人,你說我怎么就攤上這事骗卜〕枰常” “怎么了左胞?”我有些...
    開封第一講書人閱讀 152,702評論 0 342
  • 文/不壞的土叔 我叫張陵,是天一觀的道長举户。 經(jīng)常有香客問我烤宙,道長,這世上最難降的妖魔是什么俭嘁? 我笑而不...
    開封第一講書人閱讀 55,259評論 1 279
  • 正文 為了忘掉前任躺枕,我火速辦了婚禮,結(jié)果婚禮上供填,老公的妹妹穿的比我還像新娘拐云。我一直安慰自己,他們只是感情好近她,可當(dāng)我...
    茶點故事閱讀 64,263評論 5 371
  • 文/花漫 我一把揭開白布叉瘩。 她就那樣靜靜地躺著,像睡著了一般粘捎。 火紅的嫁衣襯著肌膚如雪薇缅。 梳的紋絲不亂的頭發(fā)上,一...
    開封第一講書人閱讀 49,036評論 1 285
  • 那天攒磨,我揣著相機與錄音泳桦,去河邊找鬼。 笑死咧纠,一個胖子當(dāng)著我的面吹牛蓬痒,可吹牛的內(nèi)容都是我干的。 我是一名探鬼主播漆羔,決...
    沈念sama閱讀 38,349評論 3 400
  • 文/蒼蘭香墨 我猛地睜開眼梧奢,長吁一口氣:“原來是場噩夢啊……” “哼!你這毒婦竟也來了演痒?” 一聲冷哼從身側(cè)響起亲轨,我...
    開封第一講書人閱讀 36,979評論 0 259
  • 序言:老撾萬榮一對情侶失蹤,失蹤者是張志新(化名)和其女友劉穎鸟顺,沒想到半個月后惦蚊,有當(dāng)?shù)厝嗽跇淞掷锇l(fā)現(xiàn)了一具尸體,經(jīng)...
    沈念sama閱讀 43,469評論 1 300
  • 正文 獨居荒郊野嶺守林人離奇死亡讯嫂,尸身上長有42處帶血的膿包…… 初始之章·張勛 以下內(nèi)容為張勛視角 年9月15日...
    茶點故事閱讀 35,938評論 2 323
  • 正文 我和宋清朗相戀三年蹦锋,在試婚紗的時候發(fā)現(xiàn)自己被綠了。 大學(xué)時的朋友給我發(fā)了我未婚夫和他白月光在一起吃飯的照片欧芽。...
    茶點故事閱讀 38,059評論 1 333
  • 序言:一個原本活蹦亂跳的男人離奇死亡莉掂,死狀恐怖,靈堂內(nèi)的尸體忽然破棺而出千扔,到底是詐尸還是另有隱情憎妙,我是刑警寧澤库正,帶...
    沈念sama閱讀 33,703評論 4 323
  • 正文 年R本政府宣布,位于F島的核電站厘唾,受9級特大地震影響褥符,放射性物質(zhì)發(fā)生泄漏。R本人自食惡果不足惜抚垃,卻給世界環(huán)境...
    茶點故事閱讀 39,257評論 3 307
  • 文/蒙蒙 一喷楣、第九天 我趴在偏房一處隱蔽的房頂上張望。 院中可真熱鬧讯柔,春花似錦抡蛙、人聲如沸。這莊子的主人今日做“春日...
    開封第一講書人閱讀 30,262評論 0 19
  • 文/蒼蘭香墨 我抬頭看了看天上的太陽。三九已至捣炬,卻和暖如春熊昌,著一層夾襖步出監(jiān)牢的瞬間,已是汗流浹背湿酸。 一陣腳步聲響...
    開封第一講書人閱讀 31,485評論 1 262
  • 我被黑心中介騙來泰國打工婿屹, 沒想到剛下飛機就差點兒被人妖公主榨干…… 1. 我叫王不留,地道東北人推溃。 一個月前我還...
    沈念sama閱讀 45,501評論 2 354
  • 正文 我出身青樓昂利,卻偏偏與公主長得像,于是被迫代替她去往敵國和親铁坎。 傳聞我的和親對象是個殘疾皇子蜂奸,可洞房花燭夜當(dāng)晚...
    茶點故事閱讀 42,792評論 2 345

推薦閱讀更多精彩內(nèi)容

  • iOS底層原理總結(jié) - 探尋OC對象的本質(zhì) 對小碼哥底層班視頻學(xué)習(xí)的總結(jié)與記錄。面試題部分硬萍,通過對面試題的分析探索...
    xx_cc閱讀 21,201評論 31 177
  • 轉(zhuǎn)至元數(shù)據(jù)結(jié)尾創(chuàng)建: 董瀟偉扩所,最新修改于: 十二月 23, 2016 轉(zhuǎn)至元數(shù)據(jù)起始第一章:isa和Class一....
    40c0490e5268閱讀 1,679評論 0 9
  • 1.ios高性能編程 (1).內(nèi)層 最小的內(nèi)層平均值和峰值(2).耗電量 高效的算法和數(shù)據(jù)結(jié)構(gòu)(3).初始化時...
    歐辰_OSR閱讀 29,320評論 8 265
  • OC語言基礎(chǔ) 1.類與對象 類方法 OC的類方法只有2種:靜態(tài)方法和實例方法兩種 在OC中,只要方法聲明在@int...
    奇異果好補閱讀 4,250評論 0 11
  • 上次在平臺吐槽大北做外賣app 沒想到的是 有人找到我說想投資大北 還有好多人說很喜歡大北 大部分是妹子們 直聘君...
    Boss直聘閱讀 1,565評論 2 4