iOS

[iOS] 内存对齐

2020-12-28  本文已影响0人  沉江小鱼

1. 获取内存大小的三种方式

1.1 sizeof
1.2 class_getInstanceSize
1.3 malloc_size
1.4 代码验证

可以通过代码进行验证:

#import <objc/runtime.h>

#import <malloc/malloc.h>

@interface ViewController ()

@end

@implementation ViewController

- (void)viewDidLoad {
    [super viewDidLoad];

    
    NSObject *object = [[NSObject alloc] init];
    NSLog(@"%lu",sizeof(object));
    NSLog(@"%lu",class_getInstanceSize([object class]));
    NSLog(@"%lu",malloc_size((__bridge const void *)(object)));
}

@end

输出结果:

2020-12-23 21:23:17.335020+0800 Test[3610:219003] 8
2020-12-23 21:23:17.335198+0800 Test[3610:219003] 8
2020-12-23 21:23:17.335440+0800 Test[3610:219003] 16
1.5 总结

计算类型占用内存大小,其中可以放基本数据类型、对象、指针
对于对象而言,打印的就是对象 objc 的指针大小,所以是 8
对于指针而言,64 位下是 8 个字节

计算对象实际占用的内存大小,这个跟类的属性相关,如果类中没有自定义属性,仅继承于 NSObject,则类的实例对象实际占用的内存大小是 8,可以简单理解为 8 字节对齐

计算系统为对象实际分配的内存,可以看出实际分配的和实际占用的并不相等

2. 结构体内存对齐

下面,我们首先定义两个结构体,分别计算他们的内存大小,以此来引入今天的整体:内存对齐原理。

//1、定义两个结构体
struct Mystruct1{
    char a;     //1字节
    double b;   //8字节
    int c;      //4字节
    short d;    //2字节
}Mystruct1;

struct Mystruct2{
    double b;   //8字节
    int c;      //4字节
    short d;    //2字节
    char a;     //1字节
}Mystruct2;

//计算 结构体占用的内存大小
NSLog(@"%lu-%lu",sizeof(Mystruct1),sizeof(Mystruct2));

下面是输出结果:


image.png

两个结构体只有成员变量的顺序有所区别,但是在输出结果中,他们所占用的内存大小却是不相等的,这就是内存对齐现象。

2.1 内存对齐规则

每个特定平台上的编译器都有自己的默认“对齐系数”(也叫对齐模数)。程序员可以通过预编译命令#pragma pack(n),n=1,2,4,8,16来改变这一系数,其中的n就是你要指定的“对齐系数”。在iOS中,Xcode默认为#pragma pack(8),即8字节对齐。

一般内存对齐的原则主要有3点,可以回看iOS-底层原理 02:alloc & init 源码学习中的说明。

内存对齐规则可以这么理解:

【一】 数据成员的对齐规则可以理解为min(m, n) 的公式, 其中 m表示当前成员的开始位置, n表示当前成员所需要的位数。如果满足条件 m 整除 n (即 m % n == 0), n 从 m 位置开始存储, 反之继续检查 m+1 能否整除 n, 直到可以整除, 从而就确定了当前成员的开始位置。
【二】数据成员为结构体:当结构体嵌套了结构体时,作为数据成员的结构体的自身长度作为外部结构体的最大成员的内存大小,比如结构体a嵌套结构体b,b中有char、int、double等,则b的自身长度为8
【三】最后结构体的内存大小必须是结构体中最大成员内存大小的整数倍,不足的需要补齐。

2.2 验证对齐规则

下表是各种数据类型在iOS中的占用内存大小,根据对应类型来计算结构体中内存大小:


image.jpeg

我们可以通过下图图来说明下为什么两个结构体MyStruct1 & MyStruct2的内存大小打印不一致的情况,如图所示:

image.png

结构体 MyStruct1 内存大小计算过程:

因此MyStruct1的需要的内存大小为22字节,而MyStruct1中最大变量的字节数为8,所以MyStruct1 实际的内存大小必须是8 的整数倍18向上取整到24,主要是因为24是8的整数倍,所以 sizeof(MyStruct1) 的结果是24

结构体MyStruct2 内存大小计算:

因此MyStruct2的需要的内存大小为 15字节,而MyStruct1中最大变量的字节数为8,所以MyStruct2 实际的内存大小必须是8 的整数倍15向上取整到16,主要是因为16是8的整数倍,所以 sizeof(MyStruct2) 的结果是 16

上一篇 下一篇

猜你喜欢

热点阅读