IOS底层(六): alloc相关: 内存对齐

2021-03-24  本文已影响0人  ShawnAlex

OC底层源码/原理合集

建议先看下
IOS底层(三): alloc相关1.初探 alloc, init, new源码分析,
IOS底层(四): alloc相关: 对象属性在内存中的布局

首先先介绍IOS中3种获取内存方法

sizeof

sizeof得到的是: 数据类型占用空间的大小

sizeof是一个操作符, 不是函数, 我们一般用sizeof计算内存大小时, 传入的主要对象是数据类型, 这个在编译器的编译阶段就会确定而不是运行时确定。

class_getInstanceSize

class_getInstanceSize 得到的是: 实例对象中成员变量的内存大小

class_getInstanceSizeruntime提供的api, 用于获取类的实例对象所占用的内存空间的大小, 并返回具体的字节数。

malloc_size

class_getInstanceSize 得到的是: 系统实际分配的内存大小

这个是由系统完成的, 涉及16字节内存对齐

三种获取内存方法打印结果

关于字节对齐, 我之前写的都是类的, 这次看下结构体的字节对齐, 例:

        struct Mystruct1 {
            char a;     // 1字节
            double b;   // 8字节
            int c;      // 4字节
            short d;    // 2字节
        } Mystruct1;
        
        struct Mystruct2 {
            double b;
            int c;
            short d;
            char a;
        } Mystruct2;
        
        NSLog(@"结构体1占用的内存大小 %lu", sizeof(Mystruct1));
        NSLog(@"结构体2占用的内存大小 %lu", sizeof(Mystruct2));
结果

为什么会是这个样子呢? 看到这个结果至少2个问题

内存对齐原则

验证内存对齐原则

先看下ios中数据类型的占用内存大小, 方便我们之后计算


字节数对照表

针对于上面那个例子, 先看下这个图便于理解


结构体例子计算
结构体1

结构体1需要内存22, 由于最大字节数为8, 结构体必须是8的倍数, 所以需要向上取整, 固最终结果为24

结构体2

结构体1需要内存15, 由于最大字节数为8, 结构体必须是8的倍数, 所以需要向上取整, 固最终结果为16

之前的问题解决了, 我们接下来看下结构体嵌套结构体

结构体嵌套结构体
        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;

        struct Mystruct3 {
            double b;
            int c;
            short d;
            char a;
            struct Mystruct2 str;
        } Mystruct3;

看下结构体3(结构体3为结构体2基础上嵌一个结构体2), 如果按照我们之前的定义

结构体3需要内存32, 由于最大字节数为8, 结构体必须是8的倍数, 32满足, 不需要取整, 固结果应为32, 我们验证一下

结构体嵌结构体 结构体嵌入结构体例子计算

我们再做一下验证一下

      struct Mystruct4{
            int a;
            struct Mystruct5{
                double b;
                short c;
            }Mystruct5;
        }Mystruct4;

验证一下


结构体嵌结构体

内存优化(属性重排)

上面我们看到结构体1与结构体2里面属性是一样的, 只有排列位置不一样, 结果占用内存结果也不一样。所以结构体内存大小与结构体成员内存大小的顺序有关

结构体的看完了, 我们看下类中的属性重排, 例如我们定义一个SATest

属性重排例子

main中给一些值, 然后我们读一下内存

属性重排例子

这个我们我们可以看到 name, age, hobby都读到可, 但是height, c1, c2并没有读取到, 而且isa旁边的内存段读出来是一串数字?

原因是由于苹果系统对属性进行重排, 0x0000001200006261这一串就是age, c1, c2age占4个字节,c1,c2占1个字节,通过4+1+1的方式,按照8字节补齐的方式存储在同一块内存中, 我们打印一下

属性重排例子

这里留意一下char类型是以ASCII码形式显示, 而地址为0x0000000000000000,表示person中还有未赋值

总结:

上一篇 下一篇

猜你喜欢

热点阅读