關於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

相關文章
相關標籤/搜索