OC 底層原理(2)- 對象原理(內存對齊與 calloc 分析)(隨記)

1、內存對齊原理算法

先給出一段代碼,並打印對象的存儲空間內容數組

上圖 9八、97 爲 'a'和'b'的 ascii 值

由 0x0000001200006261 能夠引出內存優化---內存拼接和內存對齊。markdown

內存對齊原則(借鑑大神的理論):數據結構

1:數據成員對⻬規則:結構(struct)(或聯合(union))的數據成員,第 一個數據成員放在offset爲0的地方,之後每一個數據成員存儲的起始位置要 從該成員大小或者成員的子成員大小(只要該成員有子成員,好比說是數組, 結構體等)的整數倍開始(好比int爲4字節,則要從4的整數倍地址開始存 儲。優化

2:結構體做爲成員:若是一個結構裏有某些結構體成員,則結構體成員要從 其內部最大元素大小的整數倍地址開始存儲.(struct a裏存有struct b,b 裏有char,int ,double等元素,那b應該從8的整數倍開始存儲.)spa

3:收尾工做:結構體的總大小,也就是sizeof的結果,.必須是其內部最大 成員的整數倍.不足的要補⻬。指針

給出一段代碼說明code

上圖打印不一樣的數據結構,數據結構內所存的數據內容同樣,但排序不同,數據結構所佔的內存大小也不一致(---二進制重排接與內存對齊)。

2、對象申請內存 VS 系統開闢內存orm

獲取內存空間大小的兩個API:對象

class_getInstanceSize:傳入一個類對象返回一個對象的實例至少申請的內存,等價於sizeof;對象裏面的屬性空間8字節對齊

malloc_size:返回系統實際分配的內存大小;系統開闢的空間16字節對齊

注:LGPerson 沒有任何屬性。

根據上圖提出兩個問題:

1)當類裏沒有任何屬性的狀況下,爲何class_getInstanceSize 獲取的內存大小要比 malloc_size 獲取到的大8?

先給出class_getInstanceSize的調用流程及最終源碼 class_getInstanceSize -> alignedInstanceSize -> word_align

此圖可看出對象裏的屬性爲 8 字節對齊。

再看 alloc 計算 size 源碼

由上圖可知,當size小於16的,就要等於16,由於在尚未屬性的時候就有個默認屬性 isa ,由於isa是指針類型,因此申請的內存空間大小就是8 ,但系統在實際分配內存空間的時候,發現申請的內存空間小於16因此就將size賦值了16,因此係統實際分配的內存就是16.這就爲何二者會相差8的緣故。

2)爲何當類裏有屬性而且大於屬性內存大於16字節的時候,class_getInstanceSize 獲取的內存是8字節對齊,malloc_size 獲取到內存是16字節對齊?

由於 alloc 建立對象並申請內存的時候的流程(關於alloc調用流程,OC 對象原理(1)有提到)會到達, _class_createInstanceFromZone 這個方法(下圖)

上圖紅色方框標出的地方 calloc 就是初始化並申請內存的地方,想要知道第二個問題答案,就須要去看看 calloc 源碼(第三部分)講解

3、calloc 原理探索

1)先下載並配置 malloc 源碼

2)追蹤流程計算size並返回的地方

calloc調用流程:calloc -> malloc_zone_calloc -> default_zone_calloc -> nano_calloc -> _nano_malloc_check_clear -> segregated_size_to_fit

segregated_size_to_fit 返回了 slot_bytes,能夠推斷這就是肯定計算size大小的算法了

其中 NANO_REGIME_QUANTA_SIZE 的定義見下圖
根據上圖可知 NANO_REGIME_QUANTA_SIZE 宏定義的值爲 16.

上圖就是得出slot_bytes結果的算法,假定 size 的值爲 40 時,這時上圖的算法就能夠解釋爲: slot_bytes = (40 + 16 - 1) >> 4 << 4;這裏 可能會以爲有些熟悉,由於上面有提到差不對的算法(8 + 8 - 1)>> 3 << 3 ,當時說的是 8 字節對齊,因此 (40 + 16 - 1) >> 4 << 4 其實 16 字節對齊。不知道爲何的同窗能夠根據 (8 + 8 - 1)>> 3 << 3 去計算一下,在計算的過程當中應該就能夠體會。綜上所訴 40 的 16 字節對齊是結果就是48 ,即 slot_bytes = 48。 這就是系統開闢的內存爲16字節的點。

如今就回答上面的第二個問題:由於前面的8字節對齊的參照物是對象裏面的屬性,而屬性的類型最大也是8字節,因此屬性內存大小8字節對齊並不會有什麼問題。可是系統分配的內存大小爲16字節對齊,是由於此時參考的因素是整個對象,要是8字節對齊就很大內存溢出的風險。

相關文章
相關標籤/搜索