关于alloc初探中alloc进入objc_alloc的缘由

alloc初探中 调试 objc 源码的时候发现了一个问题,明明点击 [[NSObject alloc] init]alloc 方法的时候进入的是 _objc_rootAlloc ,那怎么会调试的时候发现进入的是 objc_alloc ?这么诡异的问题到底出在哪里?bash

int main(int argc, const char * argv[]) {
    @autoreleasepool {
        // insert code here...
        NSObject *object = [[NSObject alloc] init];
        NSLog(@"Hello, World! %@",object);
    }
    return 0;
}

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

// Calls [cls alloc].
id
objc_alloc(Class cls)
{
    return callAlloc(cls, true/*checkNil*/, false/*allocWithZone*/);
}
复制代码

建立一个 NSObject 的子类 TestClass ,再次重现调试过程。函数

从上方的截图就能看到,先调用的是 objc_alloc ,而后调用 callAlloc 函数的 [cls alloc] ,而后才来到咱们点击 alloc 直接跳转的方法里面来,接下来就是 alloc初探 的流程了。post

打开 objc-debug.MachO 文件,在以下 symbol Table 段就能看到 objc_alloc 的符号绑定。ui

其实macho 在编译绑定符号的时候将 sel_alloc 绑定到了 objc_alloc 上。事实上 objc_alloc 并无真正开源,也不能肯定是怎么绑定到 objc_alloc 上的,可是以下代码给了思路:spa

static void 
fixupMessageRef(message_ref_t *msg)
{    
   msg->sel = sel_registerName((const char *)msg->sel);

   if (msg->imp == &objc_msgSend_fixup) { 
       if (msg->sel == SEL_alloc) {
           msg->imp = (IMP)&objc_alloc;
       } else if (msg->sel == SEL_allocWithZone) {
           msg->imp = (IMP)&objc_allocWithZone;
       } else if (msg->sel == SEL_retain) {
           msg->imp = (IMP)&objc_retain;
       } else if (msg->sel == SEL_release) {
           msg->imp = (IMP)&objc_release;
       } else if (msg->sel == SEL_autorelease) {
           msg->imp = (IMP)&objc_autorelease;
       } else {
           msg->imp = &objc_msgSend_fixedup;
       }
   } 
   
   //...
}
复制代码

若是符号绑定失败了就会触发一个这样的修复操做,明显的能看到 if (msg->sel == SEL_alloc) , msg->imp = (IMP)&objc_alloc; 这和日常使用的 Method Swizzling 很类似,不过这里只是临时交换了一下,而 Method Swizzling 是永久交换。debug

以上就是对 alloc 时候没有直接进入 objc_rootAlloc 而是进入 objc_alloc 的一点补充 。3d

相关文章
相关标签/搜索