内存字节对齐

我们可以先看看下面的结构体,观察一下结构体的内存分配情况:

struct Struct1 {
    int a;
    double b;
    int c;
    char d;
    short e;
}myStruct1;

struct Struct2 {
    int a;
    double b;
    char d;
    int c;
    short e;
}myStruct2;

NSLog(@"%lu - %lu - %lu",sizeof(myStruct1),sizeof(myStruct2));
打印结果 24 - 32

struct Struct3 {
    double b;
    char d;
    int c;
    short e;
    struct  Struct2 myStruct2;
}myStruct3;
NSLog(@"%lu",sizeof(myStruct3));
打印结果 56

struct Struct4 {
    int c;
}myStruct4;

struct Struct5 {
    double b;
    char d;
    int c;
    short e;
    struct  Struct4 myStruct4;
}myStruct5;
NSLog(@"%lu",sizeof(myStruct5));
打印结果 24

比较Struct1 和 Struct2 属性是相同的,但是属性的位置有一定的区别。这就是内存对齐的现象。
比较Struct3 和 Struct5的区别,Struct2的属性里面的最大是8,Struct4里面最大是4

内存对齐的规则

每个特定的平台上的编译器都有自己的默认“对齐系数”(也叫对齐模数)。我们可以通过预编译命令#pragma pack(n),n=1,2,4,8,16来改变这一系数,其中的n就是要指定的“对齐系数”。Xcode的对齐系数就是8。
我们在了解内存对齐之前,先看看内存对齐的原则:

  1. 数据成员对齐规则:(Struct 或 union 的数据成员)第一个数据成员放在偏移为0的位置,以后每个成员的偏移为 min(对齐系数,自身长度)的整数倍,不够整数倍的补齐。
  2. 数据成员为结构体:该数据成员的自身长度为其最大长度的整数倍开始存储
  3. 整体对齐规则:数据成员按照上述规则对齐之后,其本身也要对齐,
    对齐原则是min(对其系数,成员最大长度)的整数倍。

通过这个规则我们对Struct5做一下简单的描述
double b 8字节 存储区间 [0-7];
char d 1字节 存储区间[8-9];
int c 4字节 还有[10-15]存储段 保持4的倍数 存储区间[11-16];
short e 2字节 存储区间[17-18];
接下来 struct Struct4 myStruct4;
int c 4字节 有此仅有一个 需要的4的倍数的位置 存储区间[19-23];
保证整体对齐规则 min(对其系数,成员最大长度)为8的整数倍 即24字节

内存对齐原因

内存对齐是编译器帮我们处理的。但一个程序要求CPU读取未对齐的数据时,CPU会进入异常处理状态并且通知程序不能继续执行。因为未对齐的数据,会大大的降低CPU的性能。
CPU并不是以字节为单位来存取数据的,它会把内存当成一块一块的来,块的大小可以是2、4、8、16、32字节,每次读取都是一个固定的开销,减少内存存取次数将提升程序的性能。
我们可以假设 CPU先从地址0 读取4字节到寄存器,这时候读取的是对齐地址的数据,但从地址1读取的时候是非对齐的数据,就可能需要读取几次才能完成,然后在合成之后到寄存器。

OC内存对齐

@interface XDPerson : NSObject
@property (nonatomic, copy) NSString *name;
@property (nonatomic, assign) int age;
@property (nonatomic, assign) long height;
@property (nonatomic, copy) NSString *sex;

@property (nonatomic) char ch1;
@property (nonatomic) char ch2;

@end

- (void)viewDidLoad {
    [super viewDidLoad];
    // Do any additional setup after loading the view.
   
    XDPerson *p1 = [XDPerson alloc];
    p1.name = @"xiedong";
    p1.age = 18;
    p1.height = 180;
    p1.sex = @"男";
    p1.ch1 = 'a';
    p1.ch2 = 'b';
    
   NSLog(@"%lu - %lu",class_getInstanceSize([p1 class]),malloc_size((__bridge const void *)(p1)));
}
x/6gx p1打印结果
(lldb) x/6xg p1
0x600000ce0000: 0x00000001029570d0 0x0000001200006261
0x600000ce0010: 0x0000000102956098 0x00000000000000b4
0x600000ce0020: 0x00000001029560b8 0x0000000000000000
(lldb) po 0x00000001029570d0
XDPerson
(lldb) po 0x00000012
18
(lldb) po 0x62
98
(lldb) po 0x61
97
(lldb) po 0x0000000102956098
xiedong
(lldb) po 0x00000000000000b4
180
(lldb) po 0x00000001029560b8
男

NSLog打印的结果 40-48
  1. 可以猜到objc帮我们的对象属性做了优化处理,把size大小比较的小的 int char 组合在了一起.
  2. 然后会发现对象申请的内存空间<=系统开辟的内存空间.
    通过alloc的流程 我们会在objc源码里面看对齐方式是以8字节对齐的。
    通过calloc的流程 我们可以在malloc的源码的segregated_size_to_fit()函数里面可以看到对齐方式是以16字节对齐的。

我们可以发现 对象内部的属性有自己的内存空间是保证安全的,那么对象与对象之间是怎么保证安全的呢?

XDPerson对象内部的属性+isa占用的内存空间是28+8=36, 实际申请的内存是40 。
那么多余申请的4字节是否可以保证对象与对象之间的安全(或者说这多余的4字节是两个对象地址之间空出来的那一段呢)
结果并不是的,这多余的4字节可能是在这个对象内存空间的某个位置,并不一定在最后面。
所以系统为了保证更加的安全,以16字节对齐的方式开辟对象的内存空间,保证对象的内存空间更大,对象与对象之间更加安全。

最后编辑于
©著作权归作者所有,转载或内容合作请联系作者
  • 序言:七十年代末,一起剥皮案震惊了整个滨河市,随后出现的几起案子,更是在滨河造成了极大的恐慌,老刑警刘岩,带你破解...
    沈念sama阅读 206,723评论 6 481
  • 序言:滨河连续发生了三起死亡事件,死亡现场离奇诡异,居然都是意外死亡,警方通过查阅死者的电脑和手机,发现死者居然都...
    沈念sama阅读 88,485评论 2 382
  • 文/潘晓璐 我一进店门,熙熙楼的掌柜王于贵愁眉苦脸地迎上来,“玉大人,你说我怎么就摊上这事。” “怎么了?”我有些...
    开封第一讲书人阅读 152,998评论 0 344
  • 文/不坏的土叔 我叫张陵,是天一观的道长。 经常有香客问我,道长,这世上最难降的妖魔是什么? 我笑而不...
    开封第一讲书人阅读 55,323评论 1 279
  • 正文 为了忘掉前任,我火速办了婚礼,结果婚礼上,老公的妹妹穿的比我还像新娘。我一直安慰自己,他们只是感情好,可当我...
    茶点故事阅读 64,355评论 5 374
  • 文/花漫 我一把揭开白布。 她就那样静静地躺着,像睡着了一般。 火红的嫁衣衬着肌肤如雪。 梳的纹丝不乱的头发上,一...
    开封第一讲书人阅读 49,079评论 1 285
  • 那天,我揣着相机与录音,去河边找鬼。 笑死,一个胖子当着我的面吹牛,可吹牛的内容都是我干的。 我是一名探鬼主播,决...
    沈念sama阅读 38,389评论 3 400
  • 文/苍兰香墨 我猛地睁开眼,长吁一口气:“原来是场噩梦啊……” “哼!你这毒妇竟也来了?” 一声冷哼从身侧响起,我...
    开封第一讲书人阅读 37,019评论 0 259
  • 序言:老挝万荣一对情侣失踪,失踪者是张志新(化名)和其女友刘颖,没想到半个月后,有当地人在树林里发现了一具尸体,经...
    沈念sama阅读 43,519评论 1 300
  • 正文 独居荒郊野岭守林人离奇死亡,尸身上长有42处带血的脓包…… 初始之章·张勋 以下内容为张勋视角 年9月15日...
    茶点故事阅读 35,971评论 2 325
  • 正文 我和宋清朗相恋三年,在试婚纱的时候发现自己被绿了。 大学时的朋友给我发了我未婚夫和他白月光在一起吃饭的照片。...
    茶点故事阅读 38,100评论 1 333
  • 序言:一个原本活蹦乱跳的男人离奇死亡,死状恐怖,灵堂内的尸体忽然破棺而出,到底是诈尸还是另有隐情,我是刑警宁泽,带...
    沈念sama阅读 33,738评论 4 324
  • 正文 年R本政府宣布,位于F岛的核电站,受9级特大地震影响,放射性物质发生泄漏。R本人自食恶果不足惜,却给世界环境...
    茶点故事阅读 39,293评论 3 307
  • 文/蒙蒙 一、第九天 我趴在偏房一处隐蔽的房顶上张望。 院中可真热闹,春花似锦、人声如沸。这庄子的主人今日做“春日...
    开封第一讲书人阅读 30,289评论 0 19
  • 文/苍兰香墨 我抬头看了看天上的太阳。三九已至,却和暖如春,着一层夹袄步出监牢的瞬间,已是汗流浃背。 一阵脚步声响...
    开封第一讲书人阅读 31,517评论 1 262
  • 我被黑心中介骗来泰国打工, 没想到刚下飞机就差点儿被人妖公主榨干…… 1. 我叫王不留,地道东北人。 一个月前我还...
    沈念sama阅读 45,547评论 2 354
  • 正文 我出身青楼,却偏偏与公主长得像,于是被迫代替她去往敌国和亲。 传闻我的和亲对象是个残疾皇子,可洞房花烛夜当晚...
    茶点故事阅读 42,834评论 2 345