OC 对象原理(2)- 内存对齐与 calloc 分析(随记)

1、内存对齐原理算法

先给出一段代码,并打印对象的存储空间内容数组

上图 9八、97 为 'a'和'b'的 ascii 值

由 0x0000001200006261 能够引出内存优化---内存拼接和内存对齐。数据结构

内存对齐原则(借鉴大神的理论):优化

1:数据成员对⻬规则:结构(struct)(或联合(union))的数据成员,第 一个数据成员放在offset为0的地方,之后每一个数据成员存储的起始位置要 从该成员大小或者成员的子成员大小(只要该成员有子成员,好比说是数组, 结构体等)的整数倍开始(好比int为4字节,则要从4的整数倍地址开始存 储。3d

2:结构体做为成员:若是一个结构里有某些结构体成员,则结构体成员要从 其内部最大元素大小的整数倍地址开始存储.(struct a里存有struct b,b 里有char,int ,double等元素,那b应该从8的整数倍开始存储.)指针

3:收尾工做:结构体的总大小,也就是sizeof的结果,.必须是其内部最大 成员的整数倍.不足的要补⻬。cdn

给出一段代码说明对象

上图打印不一样的数据结构,数据结构内所存的数据内容同样,但排序不同,数据结构所占的内存大小也不一致(---二进制重排接与内存对齐)。

2、对象申请内存 VS 系统开辟内存blog

获取内存空间大小的两个API:排序

class_getInstanceSize:传入一个类对象返回一个对象的实例至少申请的内存,等价于sizeof;对象里面的属性空间8字节对齐

malloc_size:返回系统实际分配的内存大小;系统开辟的空间16字节对齐

注:LGPerson 没有任何属性。

根据上图提出两个问题:

1)当类里没有任何属性的状况下,为何class_getInstanceSize 获取的内存大小要比 malloc_size 获取到的大8?

先给出class_getInstanceSize的调用流程及最终源码 class_getInstanceSize -> alignedInstanceSize -> word_align

此图可看出对象里的属性为 8 字节对齐。

再看 alloc 计算 size 源码

由上图可知,当size小于16的,就要等于16,由于在尚未属性的时候就有个默认属性 isa ,由于isa是指针类型,因此申请的内存空间大小就是8 ,但系统在实际分配内存空间的时候,发现申请的内存空间小于16因此就将size赋值了16,因此系统实际分配的内存就是16.这就为何二者会相差8的缘故。

2)为何当类里有属性而且大于属性内存大于16字节的时候,class_getInstanceSize 获取的内存是8字节对齐,malloc_size 获取到内存是16字节对齐?

由于 alloc 建立对象并申请内存的时候的流程(关于alloc调用流程,OC 对象原理(1)有提到)会到达, _class_createInstanceFromZone 这个方法(下图)

上图红色方框标出的地方 calloc 就是初始化并申请内存的地方,想要知道第二个问题答案,就须要去看看 calloc 源码(第三部分)讲解

3、calloc 原理探索

1)先下载并配置 malloc 源码

2)追踪流程计算size并返回的地方

calloc调用流程:calloc -> malloc_zone_calloc -> default_zone_calloc -> nano_calloc -> _nano_malloc_check_clear -> segregated_size_to_fit

segregated_size_to_fit 返回了 slot_bytes,能够推断这就是肯定计算size大小的算法了

其中 NANO_REGIME_QUANTA_SIZE 的定义见下图
根据上图可知 NANO_REGIME_QUANTA_SIZE 宏定义的值为 16.

上图就是得出slot_bytes结果的算法,假定 size 的值为 40 时,这时上图的算法就能够解释为: slot_bytes = (40 + 16 - 1) >> 4 << 4;这里 可能会以为有些熟悉,由于上面有提到差不对的算法(8 + 8 - 1)>> 3 << 3 ,当时说的是 8 字节对齐,因此 (40 + 16 - 1) >> 4 << 4 其实 16 字节对齐。不知道为何的同窗能够根据 (8 + 8 - 1)>> 3 << 3 去计算一下,在计算的过程当中应该就能够体会。综上所诉 40 的 16 字节对齐是结果就是48 ,即 slot_bytes = 48。 这就是系统开辟的内存为16字节的点。

如今就回答上面的第二个问题:由于前面的8字节对齐的参照物是对象里面的属性,而属性的类型最大也是8字节,因此属性内存大小8字节对齐并不会有什么问题。可是系统分配的内存大小为16字节对齐,是由于此时参考的因素是整个对象,要是8字节对齐就很大内存溢出的风险。

相关文章
相关标签/搜索