上一篇我们进行了alloc源码的探索,这次我们紧接之前的内容,继续探索NSObject的alloc和自定义alloc的区别,以及NSObject为什么不走源码工程。
NSObject为什么不走源码工程
-
在objc4—781可编译源码中的main函数同时在NSObject和LGPerson打上断点。
-
然后跳转到alloc源码打一个断点,运行的时候需要关闭。
-
跳转objc_alloc打一个断点,运行的时候需要关闭。
在运行,断点定位到NSObject部分,打开alloc源码断点和objc_alloc断点,继续执行会发现NSObject和LGPerson都调用入objc_alloc源码。
让我们继续探索NSObject的alloc现象以及LGPerson走两次的现象
- NSObject 是iOS中的基类,所有自定义的类都需要继承自NSObject
- LGPerson 是继承自NSObject类的,重写了NSObject中的alloc方法
通过汇编我们都可以发现NSObject和LGPerson都调用objc_alloc源码,但是我们会存在疑惑
- NSObject只走objc_alloc源码
- LGPerson会走两次(alloc -> objc_alloc)
通过汇编Debug --> Debug Workflow --> 勾选 Always Show Disassemly
关闭之前的的断点,只留下main函数的断点,可以发现NSObject和LGPerson都是调用objc_alloc源码
继续在main函数LGPerson的位置打一个断点,跳转到objc_alloc源码,可以看到cls是NSArray,NSArray的父类是NSObject,在callocAlloc源码中,流程是和继承子类一样的,它就向系统发送alloc方法,但是NSArray没有alloc方法,因此开始向系统发送消息,去查找找到父类进行一系列的初始化即NSObject的alloc方法早就在系统级别就做完了。
所以由上述调试过程可以得出,LGPerson走两次的原因是首先需要去查找sel,以及对应的imp的关系,当前需要查找的是 alloc 的方法编号,但是为什么会找到objc_alloc?,这就是系统方面做的一些逻辑判断,接下来,让我们一起看看系统做了什么。
NSObject中的alloc走objc_alloc的原因
需要下载一份LLVM源码,进行探索
-
在llvm源码中搜索objc_alloc
-
搜索omf_alloc:找到tryGenerateSpecializedMessageSend,表示尝试生成特殊消息发送,这里就调用了objc_objc的逻辑,其中的关键代码是EmitObjCAlloc。
-
跳转EmitObjCAlloc的定义可以看到alloc 的处理是调用了 objc_alloc
由此可以得出 NSObject中的alloc 会走到 objc_alloc,这部分是由系统级别的消息处理逻辑,所以NSObject的初始化是由系统完成的,因此也不会走到alloc的源码工程中。
网友评论