iOS底层(一)-初探alloc

306 阅读3分钟

初探alloc

在开发中, 初始化几乎是必须会经过的一个流程.那在iOS开发中, 一个对象的初始化究竟干了一些什么.

探索源码所在位置

探索一个方法的底层实现,那么首先就是需要找到这个方法具体实现的位置.
1: 下断点 : control + in - objc_alloc
2: 下符号断点 : libobjc.A.dylib + [NSObject alloc]:
3: 汇编 libobjc.A.dylib 、objc_alloc:

源码配置

objc4-750源码
Xcode11
MacOS 10.15

源码跟踪

1. 创建一个空类,初始化该类,打上断点


2. 真机运行,跟随alloc进入源码

+ (id)alloc {
    return _objc_rootAlloc(self);
}

alloc返回了一个_objc_rootAlloc(self)方法,继续跟进

3. 进入rootAlloc方法

// Base class implementation of +alloc. cls is not nil.
// Calls [cls allocWithZone:nil].
id
_objc_rootAlloc(Class cls)
{
    return callAlloc(cls, false/*checkNil*/, true/*allocWithZone*/);
}

rootAlloc返回一个callAlloc方法. 另外可以根据官方注释了解到cls不可为空等其他信息

4. 进入callAlloc方法

// Call [cls alloc] or [cls allocWithZone:nil], with appropriate 
// shortcutting optimizations.
static ALWAYS_INLINE id
callAlloc(Class cls, bool checkNil, bool allocWithZone=false)
{
    //首先,进入callAlloc之后, 官方第一步进行的就是排除传入class是否为nil
    if (slowpath(checkNil && !cls)) return nil;
    
#if __OBJC2__
    
    if (fastpath(!cls->ISA()->hasCustomAWZ())) {
        // No alloc/allocWithZone implementation. Go straight to the allocator.
        // fixme store hasCustomAWZ in the non-meta class and 
        // add it to canAllocFast's summary
        
        //此处返回固定false. 见附图一
        if (fastpath(cls->canAllocFast())) {
            // No ctors, raw isa, etc. Go straight to the metal.
            bool dtor = cls->hasCxxDtor();
            id obj = (id)calloc(1, cls->bits.fastInstanceSize());
            if (slowpath(!obj)) return callBadAllocHandler(cls);
            obj->initInstanceIsa(cls, dtor);
            return obj;
        }
        else {
            // Has ctor or raw isa or something. Use the slower path.
            //可根据返回的obj是我们初始化返回的对象得知, 具体实现是在class_createInstance中
            id obj = class_createInstance(cls, 0);
            if (slowpath(!obj)) return callBadAllocHandler(cls);
            return obj;
        }
    }
#endif
    // No shortcuts available.
    if (allocWithZone) return [cls allocWithZone:nil];
    return [cls alloc];
}

5. 进入class_createInstance方法

id 
class_createInstance(Class cls, size_t extraBytes)
{
    return _class_createInstanceFromZone(cls, extraBytes, nil);
}

6. 进入_class_createInstanceFromZone方法

/***********************************************************************
* class_createInstance
* fixme
* Locking: none
**********************************************************************/

static __attribute__((always_inline)) 
id
_class_createInstanceFromZone(Class cls, size_t extraBytes, void *zone, 
                              bool cxxConstruct = true, 
                              size_t *outAllocatedSize = nil)
{
    //同样的防止空
    if (!cls) return nil;

    assert(cls->isRealized());

    // Read class's info bits all at once for performance
    bool hasCxxCtor = cls->hasCxxCtor();
    bool hasCxxDtor = cls->hasCxxDtor();
    bool fast = cls->canAllocNonpointer();

    //根据函数名可猜测为创建这个类所分配的大小空间(跳往6.1节)
    size_t size = cls->instanceSize(extraBytes);
    if (outAllocatedSize) *outAllocatedSize = size;

    //由第4节跳往此方法得知,第三个参数为nil, 即zone=nil, fast值根据canAllocNonpointer进入后可得知与生成isa相关,暂不做分析
    id obj;
    if (!zone  &&  fast) {
        obj = (id)calloc(1, size);
        if (!obj) return nil;
        obj->initInstanceIsa(cls, hasCxxDtor);
    } 
    else {
        //根据不同状体,调用不同的初始化方法
        if (zone) {
            obj = (id)malloc_zone_calloc ((malloc_zone_t *)zone, 1, size);
        } else {
            obj = (id)calloc(1, size);
        }
        if (!obj) return nil;

        // Use raw pointer isa on the assumption that they might be 
        // doing something weird with the zone or RR.
        
        //初始化Isa,几乎等同于initInstanceIsa, 比之少了一些断言
        obj->initIsa(cls);
    }
    //c++等相关判断,暂不做分析
    if (cxxConstruct && hasCxxCtor) {
        obj = _objc_constructOrFree(obj, cls);
    }
    //返回对象
    return obj;
}

6.1 进入instanceSize方法

size_t instanceSize(size_t extraBytes) {
    //计算所需大小
    size_t size = alignedInstanceSize() + extraBytes;
    // CF requires all objects be at least 16 bytes.
    //得知一个初始化对象最小为16个字节
    if (size < 16) size = 16;
    return size;
}

// Class's ivar size rounded up to a pointer-size boundary.
uint32_t alignedInstanceSize() {
    return word_align(unalignedInstanceSize());
}

static inline size_t word_align(size_t x) {
    //WORD_MASK 在64位下为7
    //进行字节对齐保证大小为8的倍数
    return (x + WORD_MASK) & ~WORD_MASK;
}

附图:

附一:


附二:alloc流程分析图