iOS 底层探索篇 ——alloc 流程
1. alloc
+ (id)alloc {
return _objc_rootAlloc(self);
}
在 alloc 中实际调用了 _objc_rootAlloc的方法,并把自己作为参数传入方法中。
2. _objc_rootAlloc
id
_objc_rootAlloc(Class cls)
{
return callAlloc(cls, false/*checkNil*/, true/*allocWithZone*/);
}
在_objc_rootAlloc 实际调用了 callAlloc 方法,并传入三个参数
- 对象的
class - 是否
checkNil - 以及是否
allocWithZone
3. callAlloc
static ALWAYS_INLINE id
callAlloc(Class cls, bool checkNil, bool allocWithZone=false)
{
#if __OBJC2__
if (slowpath(checkNil && !cls)) return nil;
if (fastpath(!cls->ISA()->hasCustomAWZ())) {
return _objc_rootAllocWithZone(cls, nil);
}
#endif
// No shortcuts available.
if (allocWithZone) {
return ((id(*)(id, SEL, struct _NSZone *))objc_msgSend)(cls, @selector(allocWithZone:), nil);
}
return ((id(*)(id, SEL))objc_msgSend)(cls, @selector(alloc));
}
在 callAlloc 中,
- 如果编译器处于不优化模式,并且
checkNil为true 以及 cls 不为空的情况下,返回空。 - 如果编译器处于优化模式,并且
cls没有自定义的allocWithZone,没有的话就调用,_objc_rootAllocWithZone方法。 - 如果编译器有自定义的
allocWithZone,则调用自定义的allocWithZone。
4. _objc_rootAllocWithZone
id
_objc_rootAllocWithZone(Class cls, malloc_zone_t *zone __unused)
{
// allocWithZone under __OBJC2__ ignores the zone parameter
return _class_createInstanceFromZone(cls, 0, nil,
OBJECT_CONSTRUCT_CALL_BADALLOC);
}
这里调用 _class_createInstanceFromZone方法
5. _class_createInstanceFromZone
static ALWAYS_INLINE id
_class_createInstanceFromZone(Class cls, size_t extraBytes, void *zone,
int construct_flags = OBJECT_CONSTRUCT_NONE,
bool cxxConstruct = true,
size_t *outAllocatedSize = nil)
{
ASSERT(cls->isRealized());
// Read class's info bits all at once for performance
bool hasCxxCtor = cxxConstruct && cls->hasCxxCtor();
bool hasCxxDtor = cls->hasCxxDtor();
bool fast = cls->canAllocNonpointer();
size_t size;
size = cls->instanceSize(extraBytes);
if (outAllocatedSize) *outAllocatedSize = size;
id obj;
if (zone) {
obj = (id)malloc_zone_calloc((malloc_zone_t *)zone, 1, size);
} else {
obj = (id)calloc(1, size);
}
if (slowpath(!obj)) {
if (construct_flags & OBJECT_CONSTRUCT_CALL_BADALLOC) {
return _objc_callBadAllocHandler(cls);
}
return nil;
}
if (!zone && fast) {
obj->initInstanceIsa(cls, hasCxxDtor);
} else {
// Use raw pointer isa on the assumption that they might be
// doing something weird with the zone or RR.
obj->initIsa(cls);
}
if (fastpath(!hasCxxCtor)) {
return obj;
}
construct_flags |= OBJECT_CONSTRUCT_FREE_ONFAILURE;
return object_cxxConstructFromClass(obj, cls, construct_flags);
}
在这个方法中
- 声明 obj 时候(id obj)会有一个地址,系统会分配一个
脏地址。 size = cls->instanceSize(extraBytes); ,这个决定了开辟内存的大小,大小由成员变量决定,如果小于16则返回16。如果大于16,需要用字节对齐,返回8的倍数。- 在calloc 之后,会
申请内存,并将地址返回替换掉obj的脏地址,此时地址还未绑定类,关联类的是isa。 - 在
obj->initInstanceIsa(cls, hasCxxDtor);之后,地址绑定类
流程图

482

被折叠的 条评论
为什么被折叠?



