在 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