iOS底層-內(nèi)存對齊原理

前言

在研究內(nèi)存字節(jié)對齊之前不同,先通過兩個簡單的案例了解一下內(nèi)存大小占用情況:

新建一個工程刁品,創(chuàng)建一個對象:ZLObject

  • 案例一

打印 malloc 結(jié)果如下:

  • 案例二

添加如下屬性和方法:

打印 malloc 結(jié)果如下:

結(jié)論:

  • 一個對象的實際內(nèi)存大小和實例大小可能會 不一樣秘车。例如圖中的情況拯钻,實際內(nèi)存大小是32字節(jié)莽龟,而實例大小是24字節(jié)。

  • 棧內(nèi)存8字節(jié) 對齊

為什么實際內(nèi)存大小和實例大小 不一樣 呢?原因是:底層在分配內(nèi)存的時候,做了 內(nèi)存對齊图呢,下面就深入了解 內(nèi)存對齊 的原則褐桌。

什么是內(nèi)存對齊原則照雁?

還是先通過一個案例秋泄,分析內(nèi)存如何分配的。

  • 創(chuàng)建幾個屬性夭拌,分別對屬性賦值魔熏,并打印其內(nèi)存情況。
  • 打印 obj內(nèi)存分配情況鸽扁,并分別打印其地址指向的內(nèi)容:

通過打印可知蒜绽,obj 內(nèi)存有三塊 0x600000d283c00x600000d283d0献烦、0x600000d283e0 每塊都有兩個地址滓窍,且每塊內(nèi)存都是16字節(jié)卖词,通過地址打印結(jié)果分析:

  • 第一塊的第一個地址指向 ZLObject巩那,說明是isa指針;第二個地址沒有打印到結(jié)果此蜈。
  • 第二塊的第一個地址指向 張三即横,對應(yīng)的是 name 屬性;第二個地址指向 zhang裆赵,對應(yīng)的是 nickName 屬性东囚。
  • 第三塊的第一個地址指向 北京市,對應(yīng)的是 address 屬性战授;第二個地址指向空页藻,說明沒有內(nèi)容。

為什么唯獨 0x0000001600006261 這個地址沒有打印出東西呢植兰?仔細(xì)觀察發(fā)現(xiàn)份帐,其中 0x00000016 就是數(shù)字 22,對應(yīng)的是 age 屬性楣导;0x00006261 就是 ASCIIa废境,b,對應(yīng)的就是 ab 屬性噩凹。

總結(jié):堆空間內(nèi)存是 16字節(jié) 對齊

內(nèi)存對齊原則

  • 數(shù)據(jù)成員對?規(guī)則:結(jié)構(gòu)體(struct)或聯(lián)合體(union)的數(shù)據(jù)成員巴元,第?個數(shù)據(jù)成員放在 offset0 的地?,以后每個數(shù)據(jù)成員存儲的 起始位置 要從該成員??或者成員的?成員??(只要該成員有?成員驮宴,?如說是數(shù)組逮刨,結(jié)構(gòu)體等)的整數(shù)倍開始。不夠整數(shù)倍的補齊堵泽。(?如 int 字節(jié)禀忆,則要從 整數(shù) 倍地址開始存儲。
  • 結(jié)構(gòu)體作為成員:如果?個結(jié)構(gòu)體?有某些結(jié)構(gòu)體成員落恼,則結(jié)構(gòu)體成員要從其 內(nèi)部最?元素 ??的 整數(shù)倍 地址開始存儲箩退。(比如 struct a ?存有 struct bb ?有 char佳谦,int戴涝,double 等元素,那 b 應(yīng)該從8的整數(shù)倍開始存儲钻蔑。)
  • 收尾?作:結(jié)構(gòu)體的總??啥刻,也就是 sizeof 的結(jié)果,必須是其內(nèi)部 最?成員整數(shù)倍咪笑,不?的要補?可帽。

下表是各種數(shù)據(jù)類型占用內(nèi)存大小,根據(jù)對應(yīng)類型來計算結(jié)構(gòu)體中內(nèi)存大小窗怒。

通過實際的案例來理解內(nèi)存對齊原則

案例一

創(chuàng)建兩個結(jié)構(gòu)體映跟,分析其內(nèi)存分配情況:

根據(jù)內(nèi)存對齊原則,分析以上兩個結(jié)構(gòu)體的內(nèi)存分配情況扬虚,最后再打印出結(jié)果努隙。

結(jié)果與分析的一致。

案例二

創(chuàng)建嵌套結(jié)構(gòu)體辜昵,分析其內(nèi)存分配情況:

根據(jù)內(nèi)存對齊原則荸镊,分析以上兩個嵌套結(jié)構(gòu)體的內(nèi)存分配情況,最后再打印出結(jié)果堪置。

結(jié)果與分析的一致躬存。

為什么要進行內(nèi)存對齊

內(nèi)存對齊是編譯器的管轄范圍,編譯器在編譯時會為程序中的每個數(shù)據(jù)單元安排在適當(dāng)?shù)奈恢蒙弦ㄏ牵@個過程就叫內(nèi)存對齊岭洲。

很多 CPU(如基于 Alpha,IA-64雁竞,MIPS钦椭,和 SuperH 體系的)拒絕讀取 未對齊 數(shù)據(jù)拧额。當(dāng)一個程序要求這些 CPU 讀取 未對齊 數(shù)據(jù)時,這時 CPU 會進入 異常處理狀態(tài) 并且通知程序 不能繼續(xù) 執(zhí)行彪腔。所以侥锦,如果編譯器不進行內(nèi)存對齊,那在很多平臺的上的開發(fā)將難以進行德挣。

那么恭垦,為什么這些 CPU 會拒絕讀取 未對齊 數(shù)據(jù)?是因為 未對齊 的數(shù)據(jù)格嗅,會大大降低 CPU 的性能番挺。

CPU 存取原理

程序員通常認(rèn)為內(nèi)存印象,由一個個的字節(jié)組成屯掖。

但是玄柏,你的 CPU 并 不是字節(jié) 為單位存取數(shù)據(jù)的。CPU 把內(nèi)存當(dāng)成是 一塊一塊 的贴铜,塊的大小可以是 2粪摘,48绍坝,16 字節(jié)大小徘意,因此 CPU 在讀取內(nèi)存時也是一塊一塊進行讀取的。每次內(nèi)存存取都會產(chǎn)生一個固定的 開銷轩褐,減少內(nèi)存存取次數(shù)將提升程序的 性能椎咧。所以 CPU 一般會以 2/4/8/16/32 字節(jié)為單位來進行存取操作。我們將上述這些存取單位也就是塊大小稱為(memory access granularity)內(nèi)存存取粒度把介。

為了說明內(nèi)存對齊背后的原理勤讽,我們通過一個例子來說明從未對齊地址對齊地址 讀取數(shù)據(jù)的差異。

案例

在一個存取粒度為 8 字節(jié)的內(nèi)存中劳澄,先從地址 0 讀取 8 個字節(jié)到寄存器地技,然后從地址 3 讀取 8 個字節(jié)到寄存器。

  • 當(dāng)從地址 0 開始讀取數(shù)據(jù)時秒拔,讀取 對齊地址 的數(shù)據(jù),直接通過 一次 讀取就能完成飒硅。
  • 當(dāng)從地址 3 開始讀取數(shù)據(jù)時砂缩,讀取 非對齊地址 的數(shù)據(jù),需要讀取 兩次 數(shù)據(jù)才能完成三娩。
讀取對齊地址的數(shù)據(jù)

讀取 非對齊地址 的數(shù)據(jù)后庵芭,還要將 0-7 的數(shù)據(jù)向上偏移 3 字節(jié),將 8-F 的數(shù)據(jù)向下偏移 5 字節(jié)雀监。最后再將兩塊數(shù)據(jù)合并放入寄存器双吆。

讀取非對齊地址的數(shù)據(jù)

對一個 內(nèi)存未對齊 的數(shù)據(jù)進行了這么多額外的操作眨唬,這對 CPU 的開銷很大,大大降低了CPU性能好乐。所以才會進行內(nèi)存對齊匾竿。

總結(jié)

  • 棧內(nèi)存8字節(jié) 對齊
  • 堆內(nèi)存16字節(jié) 對齊
最后編輯于
?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請聯(lián)系作者
  • 序言:七十年代末,一起剝皮案震驚了整個濱河市蔚万,隨后出現(xiàn)的幾起案子岭妖,更是在濱河造成了極大的恐慌,老刑警劉巖反璃,帶你破解...
    沈念sama閱讀 221,198評論 6 514
  • 序言:濱河連續(xù)發(fā)生了三起死亡事件昵慌,死亡現(xiàn)場離奇詭異,居然都是意外死亡淮蜈,警方通過查閱死者的電腦和手機斋攀,發(fā)現(xiàn)死者居然都...
    沈念sama閱讀 94,334評論 3 398
  • 文/潘曉璐 我一進店門,熙熙樓的掌柜王于貴愁眉苦臉地迎上來梧田,“玉大人蜻韭,你說我怎么就攤上這事∈量郏” “怎么了肖方?”我有些...
    開封第一講書人閱讀 167,643評論 0 360
  • 文/不壞的土叔 我叫張陵,是天一觀的道長未状。 經(jīng)常有香客問我俯画,道長,這世上最難降的妖魔是什么司草? 我笑而不...
    開封第一講書人閱讀 59,495評論 1 296
  • 正文 為了忘掉前任艰垂,我火速辦了婚禮,結(jié)果婚禮上埋虹,老公的妹妹穿的比我還像新娘猜憎。我一直安慰自己,他們只是感情好搔课,可當(dāng)我...
    茶點故事閱讀 68,502評論 6 397
  • 文/花漫 我一把揭開白布胰柑。 她就那樣靜靜地躺著,像睡著了一般爬泥。 火紅的嫁衣襯著肌膚如雪。 梳的紋絲不亂的頭發(fā)上袍啡,一...
    開封第一講書人閱讀 52,156評論 1 308
  • 那天踩官,我揣著相機與錄音,去河邊找鬼境输。 笑死蔗牡,一個胖子當(dāng)著我的面吹牛颖系,可吹牛的內(nèi)容都是我干的。 我是一名探鬼主播辩越,決...
    沈念sama閱讀 40,743評論 3 421
  • 文/蒼蘭香墨 我猛地睜開眼嘁扼,長吁一口氣:“原來是場噩夢啊……” “哼!你這毒婦竟也來了区匣?” 一聲冷哼從身側(cè)響起偷拔,我...
    開封第一講書人閱讀 39,659評論 0 276
  • 序言:老撾萬榮一對情侶失蹤,失蹤者是張志新(化名)和其女友劉穎亏钩,沒想到半個月后莲绰,有當(dāng)?shù)厝嗽跇淞掷锇l(fā)現(xiàn)了一具尸體,經(jīng)...
    沈念sama閱讀 46,200評論 1 319
  • 正文 獨居荒郊野嶺守林人離奇死亡姑丑,尸身上長有42處帶血的膿包…… 初始之章·張勛 以下內(nèi)容為張勛視角 年9月15日...
    茶點故事閱讀 38,282評論 3 340
  • 正文 我和宋清朗相戀三年蛤签,在試婚紗的時候發(fā)現(xiàn)自己被綠了。 大學(xué)時的朋友給我發(fā)了我未婚夫和他白月光在一起吃飯的照片栅哀。...
    茶點故事閱讀 40,424評論 1 352
  • 序言:一個原本活蹦亂跳的男人離奇死亡震肮,死狀恐怖,靈堂內(nèi)的尸體忽然破棺而出留拾,到底是詐尸還是另有隱情戳晌,我是刑警寧澤,帶...
    沈念sama閱讀 36,107評論 5 349
  • 正文 年R本政府宣布痴柔,位于F島的核電站沦偎,受9級特大地震影響,放射性物質(zhì)發(fā)生泄漏咳蔚。R本人自食惡果不足惜豪嚎,卻給世界環(huán)境...
    茶點故事閱讀 41,789評論 3 333
  • 文/蒙蒙 一、第九天 我趴在偏房一處隱蔽的房頂上張望谈火。 院中可真熱鬧侈询,春花似錦、人聲如沸糯耍。這莊子的主人今日做“春日...
    開封第一講書人閱讀 32,264評論 0 23
  • 文/蒼蘭香墨 我抬頭看了看天上的太陽谍肤。三九已至啦租,卻和暖如春,著一層夾襖步出監(jiān)牢的瞬間荒揣,已是汗流浹背。 一陣腳步聲響...
    開封第一講書人閱讀 33,390評論 1 271
  • 我被黑心中介騙來泰國打工焊刹, 沒想到剛下飛機就差點兒被人妖公主榨干…… 1. 我叫王不留系任,地道東北人恳蹲。 一個月前我還...
    沈念sama閱讀 48,798評論 3 376
  • 正文 我出身青樓,卻偏偏與公主長得像俩滥,于是被迫代替她去往敵國和親嘉蕾。 傳聞我的和親對象是個殘疾皇子,可洞房花燭夜當(dāng)晚...
    茶點故事閱讀 45,435評論 2 359

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