今天探索的是內(nèi)存是如何分配,如何對齊的, 一般我們在開發(fā)時通常都會用到LLDB斷點調(diào)試, 看看下圖對JJPerson的斷點打印
通過斷點打印這個person對象,以下是通過lldb指令打印輸出的值
x/6gx 0x600003f51590 (打印6個內(nèi)存段)
輸出
0x600003f51590: 0x00000001094407d0 0x0000001400006261
0x600003f515a0: 0x000000010943e038 0x000000010943e058
0x600003f515b0: 0x0000000000000000 0x0000000000000000
再繼續(xù)打印這些地址康康呢
po 0x600003f51590 --> <JJPerson: 0x600003f51590>
po 0x00000001094407d0 --> JJPerson
po 0x000000010943e038 --> daju
po 0x00000014 --> 20
po 0x62 --> 98 (98是不是對應著ascll碼中的b)
po 0x61 -->97 (97是不是對應著ascll碼中的a)
是不是有很多疑問?比如:
為啥還有0x0000000000000000呢?
c1 c2為啥共用的一段內(nèi)存呢, 但是可以分開打印?
age為什么要長一點?
為啥c1 c2在前面呢?
看看上面這個圖就知道了,因為不同類型所占字節(jié)大小不同, 蘋果系統(tǒng)為了方便讀取, 節(jié)約內(nèi)存所以對我們的對象的內(nèi)存進行了字節(jié)對齊,重排.
內(nèi)存對齊原則
1:數(shù)據(jù)成員對?規(guī)則:結構(struct)(或聯(lián)合(union))的數(shù)據(jù)成員库继,第
一個數(shù)據(jù)成員放在offset為0的地方阔挠,以后每個數(shù)據(jù)成員存儲的起始位置要
從該成員大小或者成員的子成員大小(只要該成員有子成員风响,比如說是數(shù)組,結構體等)的整數(shù)倍開始(比如int為4字節(jié),則要從4的整數(shù)倍地址開始存儲皿曲。 min(當前開始的位置mn)m=9n=4
9 10 11 12
2:結構體作為成員:如果一個結構里有某些結構體成員,則結構體成員要從其內(nèi)部最大元素大小的整數(shù)倍地址開始存儲.(struct a里存有struct b,b
里有char,int ,double等元素,那b應該從8的整數(shù)倍開始存儲.)
3:收尾工作:結構體的總大小,也就是sizeof的結果,.必須是其內(nèi)部最大 成員的整數(shù)倍.不足的要補?。
如何理解上面的意思, 我們以這個結構體為例子
struct LGStruct1 {
double a; // 8字節(jié) (0-7)
char b; // 1字節(jié) [8 ] (8)
int c; // 4字節(jié) [9 4] 9 10 11 (12 13 14 15)
short d; // 2字節(jié) [16 2] (16 17)
}struct1;
NSLog(@"struct1 - %lu",sizeof(struct1));
輸出
2020-09-09 00:42:58.246389+0800 001-內(nèi)存對齊原則[51039:4654930] struct1 - 24
內(nèi)存對齊規(guī)則1:開始位置必須是所占字節(jié)數(shù)的整數(shù)倍吴侦,才能開始存屋休。
(舉例:char b,由于開始位置是所占字節(jié)數(shù)的整數(shù)倍可以直接存,int c 备韧,開始位置是從9劫樟,并不是4的整數(shù)倍,所以從12開始存)
存儲大小是:18{0-17}
由于結構體中存在double為最大字節(jié)數(shù):8
(內(nèi)存對齊規(guī)則3:所占內(nèi)存必須是最大字節(jié)數(shù)的整數(shù)倍织堂。所以必須是8的整數(shù)倍叠艳。18-->24)
所以所占內(nèi)存大小是24.
struct JJStruct2 {
int a; //4字節(jié) (0-7)
double b; //8字節(jié) (8 9 10 11 12 13 14 15)
char c; //1字節(jié) (16)
short d; //2字節(jié) (18 19)
}struct2;
// 20 -> 24
20不是8的整數(shù)倍,所以所占內(nèi)存是24
struct JJStruct3 {
int a; //4字節(jié) (0 7)
double b; //8字節(jié) (8 9 10 11 12 13 14 15)
char s; //1字節(jié) (16)
short cc; //2字節(jié) (18 19)
struct JJStruct2 *structoo; //8 (24 25 26 27 28 29 30 31)
} jjstruct3;
//32 -> 32
NSLog(@"%lu-%lu - %lu",sizeof(struct1),sizeof(struct2), sizeof(jjstruct3)); NSLog(@"%lu-%lu",sizeof(struct1),sizeof(struct2));
輸出
2020-09-09 00:25:39.871666+0800 001-內(nèi)存對齊原則[50912:4644070] 24-24 - 32