阅读 128
OC对象底层原理探索(2)

OC对象底层原理探索(2)

前言:前面一片文章,我们对alloc的源码进行了一些探究,不知道各位有没有发现一些问题,callAlloc为什么会走两遍。下面带着问题我们来分析

1、问题发现

alloc 断点后 进入汇编查看 汇编代码 其实第一步走的并不是 _objc_rootAlloc

如图 汇编代码应该调用的是 objc_alloc方法 而不是_objc_rootAlloc

image.png

2、通过源码分析

在alloc处打上断点 并查看堆栈信息 如下:

image.png main 方法后 并非直接调用alloc 而是调用了一次 objc_alloc 这就和我们之前分析汇编吻合了

3、为什么第一次不是直接走alloc 而是走了objc_alloc呢?

通过代码来分析 第一次肯定是 调用了alloc方法,了解 selimp的应该知道,有可能是在 main方法之前偷偷的把alloc 对应的imp 给改了呢 改成了objc_alloc 那我们就来找下 在加载dyld的时候 有没有进行一些操作 通过llvm源码来找

1.1 通过LLVM源码查找objc_alloc

如图:

image.png 基本可以确定的是 在调用alloc时候 是转成调用objc_alloc了

1.2分析objc_alloc

找到objc_alloc方法 再次运行 会调用callAlloc方法 在callAlloc 方法中断点 再次运行会走 objc_msgSend)(cls, @selector(alloc))方法 再次走到alloc 方法 然后再调用 _objc_rootAlloc -> callAlloc -> allocWithZone -> _objc_rootAllocWithZone -> createInstanceFromZone -> instanceSize -> initInstanceIsa -> return obj

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));
}
复制代码
总结

整个alloc 流程 objc_alloc -> callAlloc -> objc_msgSend -> alloc-> _objc_rootAlloc -> callAlloc -> _objc_rootAllocWithZone ->_class_createInstanceFromZone -> cls->instanceSize -> calloc -> initinstanceIsa

image.png

文章分类
iOS
文章标签