ios开发之Alloc底层原理探究

2020-12-09 09:50:10 浏览数 (1)

1.为什么要用alloc?

我们在oc开发当中经常使用alloc来为对象申请开辟内存空间例如

School *s1 = [School alloc]

2.alloc 的流程

在苹果开源的源码文件NSObject.mm中可以轻易找到alloc的流程。如下

objetc_alloc->alloc->_objc_rootAlloc->callAlloc->_objc_rootAllocWithZone->_class_createInstanceFromZone

可以知道一点在_class_createInstanceFromZone后会有三个条件判断。这三个条件判断就是alloc的精髓也既是我们需要研究的对象

1.size= cls->instanceSize

这行代码可以清晰一个问题,我们alloc的时候首先需要知道实例化对象的类 需要多少/多大的内存空间。

instanceSize->cache.fastInstanceSize

到这里我们可以看到fastInstanceSize 下面有两行代码以及英文注释:(通过setFastInstanceSize函数移除已经添加的MASK)

继续深入下去会发现有三个问题1.flags是什么 2.mask掩码作用 3.为什么要进行逻辑与运算

1.size=_flags & MASK (mask其实只是一个定义在已初始化区里的一个常量=8)

这里我们可以看见size=16 也既证明了一个空对象能占16大小空间,size的大小取决于类的属性多少

2.align16(size extra - 宏8byte)

return (x 15) & ~15

这句代码是经典的16字节对齐算法,具体过程请参照c语言-逻辑运算.

2.obj=(id)calloc(1,size)

calloc->malloc_zone_calloc->zone->calloc->nano_malloc_check_clear->segregated_size_to_fit

千呼万唤始出来,终于找到关键函数

segregated_size_to_fit()

k=(size nano_size -1 ) >> shift_nano_quantum

k=(x 15)>>4

slot_bytes=k<<4

3.obc->initInstanceIsa(cls,hasCxxDtor)

对象在clang编译下会变成c 的结构体,大小为8字节*8=64位

initIsa->isa_t->newisa

特点:isa_t的结构是联合体位域union 包含cls bits;

isa-unionisa-union

ISA_BITFIELD 这里就是区分arm64架构和x86_64的地方 区别在与

DefineDefine

nonpointer:1 是否对isa开启指针优化 0:代表纯isa指针 1:代表isa中包含了类信息,对象引用计数等

has_assoc:1是否有关联对象

has_cxx_dtor:1 是否有c 扩展

uintptr_t shiftcls :33/44 arm/x86 存放类信息

magic:6 是否初始化空间

weakly_referenced:1 是否被指向一个arc弱引用变量,没有可以更快的释放

deallocating:1 析构

has_sidetable_rc:1 散列表 当引用计数大于10时,则需要借用该变量存储进位

extra_rc:19 应用计数

newisa函数做了以下几件事

1.给bits cxx_dtor shiftcls 赋值

newisa.bits=ISA_MAGIC_VALUE; 0x001d800000000001ULL =59

newisa.has_cxx_dtor=hasCxxDtor

newisa.shiftcls = cls>>3左移三位 把noptr asoc cxx 这三个敏感信息移出

isaisa

说明了isa关联了指针和类

isa & 0x00007ffffffffff8ULL = class

自此 通过initIsa(cls,true,hasCxxDtor)关联类和拓展 就完成了alloc下class_createInstanceFromZone的三个步骤。

我们可以发现知识涉及:isa结构 类 算法 缓存 逻辑运算 等等。

0 人点赞