1. 程式人生 > 其它 >iOS底層原理02-alloc原始碼分析

iOS底層原理02-alloc原始碼分析

首先,從最熟悉的入手 - 物件,看看這三個物件的內容,記憶體地址和指標地址。

LGPerson *p1 = [LGPerson alloc];
LGPerson *p2 = [p1 init];
LGPerson *p3 = [p1 init];
LGNSLog(@"%@ - %p - %p",p1,p1,&p1);
LGNSLog(@"%@ - %p - %p",p2,p2,&p2);
LGNSLog(@"%@ - %p - %p",p3,p3,&p3);

輸出結果:

可以看出3個物件指向的是同一個記憶體空間,所以其內容記憶體地址相同的,但是物件的指標地址是不同的。

alloc 的流程

callAlloc做了一個編譯優化

計算所需開闢記憶體的大小流程

記憶體位元組對齊原則

在解釋為什麼需要16位元組對齊之前,首先需要了解記憶體位元組對齊的原則,主要有以下三點

資料成員對齊規則:struct 或者 union 的資料成員,第一個資料成員放在offset為0的地方,以後每個資料成員儲存的起始位置要從該成員大小或者成員的子成員大小(只要該成員有子成員,比如資料、結構體等)的整數倍開始(例如int在32位機中是4位元組,則要從4的整數倍地址開始儲存)
資料成員為結構體:如果一個結構裡有某些結構體成員,則結構體成員要從其內部最大元素大小的整數倍地址開始儲存(例如:struct a裡面存有struct b,b裡面有char、int、double等元素,則b應該從8的整數倍開始儲存)
結構體的整體對齊規則:結構體的總大小,即sizeof的結果,必須是其內部做大成員的整數倍,不足的要補齊

為什麼需要16位元組對齊

需要位元組對齊的原因,有以下幾點:

通常記憶體是由一個個位元組組成的,cpu在存取資料時,並不是以位元組為單位儲存,而是以塊為單位存取,塊的大小為記憶體存取力度。頻繁存取位元組未對齊的資料,會極大降低cpu的效能,所以可以通過減少存取次數來降低cpu的開銷
16位元組對齊,是由於在一個物件中,第一個屬性isa佔8位元組,當然一個物件肯定還有其他屬性,當無屬性時,會預留8位元組,即16位元組對齊,如果不預留,相當於這個物件的isa和其他物件的isa緊挨著,容易造成訪問混亂
16位元組對齊後,可以加快CPU讀取速度,同時使訪問更安全,不會產生訪問混亂的情況

位元組對齊-總結

在位元組對齊演算法中,對齊的主要是物件,而物件的本質則是一個 struct objc_object的結構體,
結構體在記憶體中是連續存放的,所以可以利用這點對結構體進行強轉。
蘋果早期是8位元組對齊,現在是16位元組對齊
例如:
struct LGStruct1 {
double a; // 8 (0-7)
char b; // 1 [8 1] (8)
int c; // 4 [9 4] 9 10 11 (12 13 14 15) /*9不是4的倍數,從4的倍數開始算起,佔4個位元組,就是(12,13,14,15)**/
short d; // 2 [16 2] (16 17)
}struct1;

// 內部需要的大小為: 17
// 最大屬性 : 8
// 結構體整數倍: 24