了解内存对齐原理

2020-09-12  本文已影响0人  _涼城
对象的内存空间
首先创建一个Person
@interface Person : NSObject

@property (nonatomic, copy) NSString *name;
@property (nonatomic, copy) NSString *nickName;

@property (nonatomic, assign) int age;
@property (nonatomic, assign) long height;

@property (nonatomic) char c1;
@property (nonatomic) char c2;
@end
实例化一个Person对象
Person *person = [Person alloc];
person.name      = @"Cc";
person.nickName  = @"cc";
person.age       = 18;
person.c1        = 'a';
person.c2        = 'b';
调试对象地址的信息
16字节输出信息.png

我们可以正常输出字符串对象属性的信息,但是无法找出基本数据类型信息。

调试基本数据类型信息
输出基本数据类型信息.png

这是因为苹果通过属性重排使得完成了内存优化,这种内存对齐方式来源于结构体内存对齐。

结构体内存对齐
结构体对象的内存

首先创建两个结构体对象Struct1

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

Struct2

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

通过SizeOf函数获取Struct1Struct2的大小分别是2416,那么为什么占用的内存大小不相等呢?

在探索结构体内存之前,我们需要先了解内存对齐的原则。

内存对齐的原则
  1. 数据成员对⻬规则

    结构体或联合体的数据成员,第⼀个数据成员放在offset为0的地⽅以后每个数据成员存储的起始位置要从该成员⼤⼩或者成员的⼦成员⼤⼩的整数倍开始。

    例如,int为4字节,则要从4的整数倍地址开始存储

  2. 结构体作为成员

    如果⼀个结构⾥有某些结构体成员,则结构体成员要从其内部最⼤元素⼤⼩的整数倍地址开始存储。

    例如,struct a⾥存有struct b,b⾥有char,int ,double等元素,那b应该从8的整数倍开始存储

  3. 结构体的总⼤⼩

    结构体的大小必须是其内部最大成员的整数倍,不足的要补齐。

计算结构体内存的大小

根据数据类型对应的内存大小以及内存对齐的原则,计算Struct1Struct2的大小。

属性重排

根据上述可以得出一个结论,结构体内存大小与结构体成员内存大小的顺序有关,苹果中将类中的属性进行重排,来达到优化内存的目的。

获取内存大小的三种方式

sizeof,获取该数据类型占用空间的大小。

class_getInstanceSize,获取实例对象中成员变量的内存大小,是采用8字节对齐,参照的对象的属性内存大小。

malloc_size,获取系统实际分配的内存大小,采用16字节对齐,参照的整个对象的内存大小,对象实际分配的内存大小必须是16的整数倍。

上一篇 下一篇

猜你喜欢

热点阅读