alloc扩展

alloc的底层源码探索过程中发现了callAlloc被调用了两次,带着疑惑,在初始化YDPerson时下了一个断点,并开启查看汇编模式

通过上图汇编发现在断点处调用的符号是objc_alloc,不应该是alloc吗?
于是在objc源码中在allocobjc_alloc都下断点。

通过断点调试发现没有先执行alloc,而是先是来调用了objc_alloc执行了一次callAlloc,然后调用了alloc接着调用了_objc_rootAlloc然后又调用了一次callAlloc,虽然通过断点跟流程找到了两次执行的过程,但苹果为何要这样做呢?,于是开始在 objc4-818.2源码中疯狂查找objc_alloc,最后在objc-runtime-new.mm文件中找到了一些线索

通过上图可以发现函数fixupMessageRefalloc做了处理,selallocimp重新指向到了objc_alloc,说明做了hook处理,接着在源码中查找fixupMessageRef的调用

最后在 _read_images函数中找到了fixupMessageRef函数的调用,在函数注释中提示了_read_images的调用函数是map_images_nolock

在函数map_images中调用了函数map_images_nolock

最终我们在_objc_init函数内的_dyld_objc_notify_register中查找到了map_images的调用

通过一系列的断点跟踪,最终反推出了调用的流程,发现最终执行是在_objc_init,然而_objc_init是在dyld动态链接后才执行的,得出结论fixupMessageRef消息的修复是在dyld之后,那么消息的绑定即selimp的绑定肯定是在dyld之前才行,就是在编译阶段了,接下来通过llvm源码继续查找objc_alloc

通过不停的搜索alloc,最终在tryGenerateSpecializedMessageSend函数中找到了case OMF_alloc:这里对消息类型的allocallocWithZone都做了特殊的处理,当消息为alloc时,直接对消息的接收者调用了objc_alloc,而tryGenerateSpecializedMessageSend又来至于GeneratePossiblySpecializedMessageSend,在这个函数里有两个判断,针对这个消息接收者首先会尝试发送一个特殊的消息,通过tryGenerateSpecializedMessageSend的实现可知,这个特殊的消息就是当消息为alloc时就发送一个特殊的objc_alloc消息,如果已经发送过了就直接走正常的消息发送即alloc消息,这也就验证了为什么alloc会走objc_alloc,原来苹果底层在编译阶段进行了llvm的优化。

最后编辑于
©著作权归作者所有,转载或内容合作请联系作者
【社区内容提示】社区部分内容疑似由AI辅助生成,浏览时请结合常识与多方信息审慎甄别。
平台声明:文章内容(如有图片或视频亦包括在内)由作者上传并发布,文章内容仅代表作者本人观点,简书系信息发布平台,仅提供信息存储服务。

相关阅读更多精彩内容

友情链接更多精彩内容