在 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