美文网首页
iOS底层原理--02 :内存对齐原理

iOS底层原理--02 :内存对齐原理

作者: 爱闹的凡 | 来源:发表于2020-09-16 19:26 被阅读0次
  • 研究内存对齐原理之前,我们先要熟悉下表:


    类型对应表.jpg

    知道对应的内存大小了,接下来我们需要获取内存,验证是否正确。

  • 验证内存的三种方式:
    1、sizeof
    2、class_getInstanceSize
    3、malloc_size

sizeof
  • 1、sizeof是一个操作符,不是函数
  • 2、sizeof计算的是对象数据类型的大小,这个大小在编译时确定的而不是运行时
  • 3、sizeof最终得到的数据是该数据类型占用空间的大小,当sizeof(结构体)的时候,获取到的是对象指针大小,我们知道一个指针的内存大小是8,所以sizeof获取内存大小时可以放基本数据类型、对象、指针、
calss_getInstanceSize

这个方法是runtime提供的api,用于获取类的实例对象所占用的内存大小,并返回具体的字节数,其本质就是获取实例对象中成员变量的内存大小

malloc_size

这个函数是 获取系统实际分配的内存大小

通过下面的函数打印结果验证上面的说法:

#import <Foundation/Foundation.h>
#import "LGPerson.h"
#import <objc/runtime.h>
#import <malloc/malloc.h>

int main(int argc, const char * argv[]) {
    @autoreleasepool {
        NSObject *objc = [[NSObject alloc] init];
        NSLog(@"objc对象类型占用的内存大小:%lu",sizeof(objc));
        NSLog(@"objc对象实际占用的内存大小:%lu",class_getInstanceSize([objc class]));
        NSLog(@"objc对象实际分配的内存大小:%lu",malloc_size((__bridge const void*)(objc)));
    }
    return 0;
}

打印结果如下:

三种获取内存方式的打印结果.png

从打印的结果看实际分配的内存和实际内存大小并不相等,不相等的原因是因为内存16字节对齐的原则导致的,内存字节对齐的原理主要有以下三点:
1、数据成员对齐规则:struct 或者 union 的数据成员,第一个数据成员放在offset=0的地方,以后每个数据成员存储的其实位置要从该成员大小或者成员子成员大小(只要该成员有子成员比如结构体)的整数倍开始(例如int在32位机中占4字节,则要从4的整数倍地址开始存储)
2、数据成员位结构体:如果一个结构体里有某些结构体成员,则结构体成员要从其内部最大元素大小的整数倍地址开始存储(例如:struct a里面存有struct b,b里面有char、int、double等元素,则b应该从8的整数倍开始存储)
3、结构体的整体对齐规则:结构体的总大小,即 sizeof的结果必须是其内部最大成员的整数倍,不足的要补齐

为什么是16位对齐

1、通常内存是一个个字节组成的,cpu在存取数据时,并不是以字节为单位存储,而是以块为单位存取,块的大小为内存存取力度,频繁存取字节未对齐的数据,会极大降低CPU的性能,所以可以通过减少存取次数来降低cup的开销
2、16字节对齐是因为一个对象中的第一个属性isa8字节,当然对象中肯定还有其他属性,当无属性时会预留8字节,即16字节对齐,如果不预留相当于这个对象的isa和其它对象的isa紧挨着,容易造成访问混乱
3、16字节对齐后,可以加快cpu的存取速度,同时增加访问安全性

16字节对齐的算法
  • 首先将原始的内存 8 与 size_t(15)相加,得到 8 + 15 = 23
  • 将 size_t(15) 即 15进行(取反)操作,(取反)的规则是:1变为0,0变为1
  • 最后将 23 与 15的取反结果 进行 &(与)操作,&(与)的规则是:都是1为1,反之为0,最后的结果为 16,即内存的大小是以16的倍数增加的


    内存16字节对齐算法.png

结构体内存对齐

接下来我们定义两个结构体分别计算他们的大小:

//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));

输出结果为:

a0000000bbbbbbbbccccdd =24
bbbbbbbbccccdda0=16 //结构体的大小(sizeof)必须是最大成员的整数倍,所以15位需要补一位最后结果是16

两个结构体乍一看,没什么区别,其中定义的变量 和 变量类型都是一致的,唯一的区别只是在于定义变量的顺序不一致,那为什么他们做占用的内存大小不相等呢?其实这就是iOS中的内存字节对齐现象

可以将内存对齐原则可以理解为以下两点:

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

相关文章

  • iOS--OC底层原理文章汇总

    OC底层原理01—alloc + init + new原理OC底层原理02—内存对齐OC底层原理03— isa探究...

  • iOS底层原理--02 :内存对齐原理

    研究内存对齐原理之前,我们先要熟悉下表:类型对应表.jpg知道对应的内存大小了,接下来我们需要获取内存,验证是否正...

  • OC底层原理汇总

    OC底层原理(一).alloc实际调用流程分析OC底层原理(二).内存分配与内存对齐OC底层原理(三)、isa、对...

  • iOS-底层原理 05:内存对齐原理

    iOS 底层原理 文章汇总 在探讨内存对齐原理之前,首先介绍下iOS中获取内存大小的三种方式 获取内存大小的三种方...

  • ios底层原理 :内存对齐原理

    先介绍一下ios获取内存的三种方式 获取内存大小的三种方式 sizeof class_getInstanceSiz...

  • iOS内存对齐

    这篇文章我们来探索一下iOS内存对齐的原理,在探索完内存对齐原理之后,你就会明白内存对齐的好处。 在讲述内存对齐时...

  • iOS底层原理--内存对齐

    在iOS底层原理--alloc&init&new这篇文章中,我们认识到了字节对齐。那么,我们回顾一下什么是字节对齐...

  • iOS底层-内存对齐原理

    前言 在研究内存字节对齐之前,先通过两个简单的案例了解一下内存大小占用情况: 新建一个工程,创建一个对象:ZLOb...

  • iOS-底层原理 06:malloc 源码分析 思路

    iOS-底层原理 06:malloc 源码分析 在iOS-底层原理 02:alloc & init & new 源...

  • iOS底层原理之内存对齐原理

    内存对齐是我们定义数据结构中一个必须要了解的知识点,内存对齐的目的在于能让系统从内存中快速的查找并且获取到我们想要...

网友评论

      本文标题:iOS底层原理--02 :内存对齐原理

      本文链接:https://www.haomeiwen.com/subject/ybazektx.html