0
点赞
收藏
分享

微信扫一扫

IOS底层(五): alloc相关: NSObject, alloc源码分析

攻城狮Chova 2021-09-19 阅读 55
日记本

建议先看下 IOS底层(三): alloc相关1.初探 alloc, init, new源码分析

先看个例子


NSObject , alloc方法里面 加断点, 运行我们会发现竟然没有走+ (id)alloc方法

那么NSObject在走的是哪个方法呢?

打开 DebugDebug Workflow勾选 Always Show Disassemly进行汇编调试

alloc方法这边打个断点, 运行一下

我们可以看到都走了一个objc_alloc 方法
全局搜索 objc_alloc,可看到有一个这个方法

objc_alloc中加一个断点,先暂时关闭汇编, 重新运行下可看到, 的确走到这里来了

那么为什么NSObject走的是objc_alloc(Class cls) 这个方法?

原因主要是: NSObject 系统级别帮我们走完

这里我们需要一份LLVM源码(llvm-project, 是系统级别的源码)来具体分析下, objc_alloc是什么时候有的, 而它又与alloc有什么区别。
LLVM下载地址

查找下
通过alloc字符串或者omf_alloc:搜索, 找到tryGenerateSpecializedMessageSend方法

这里可以看到, 如果当前方法sel如果是alloc就会调用一个EmitObjCAlloc方法, 点进去看一下

可以看到这里调用了一个objc_alloc。由此可以得出NSObject中的alloc会走到objc+alloc, 其实这部分是由系统级别的消息处理逻辑, 固NSObject的初始化是由系统完成, 因此不会走传统的alloc的源码中。

j接下来我们看下自定义类SATest

NSObject *objc = [NSObject alloc];
SATest *objc1 = [SATest alloc];

首先SATest 是继承NSObject的, NSObject是其根类/基类/父类, 所有自定义的类都继承于NSObject。

我们由LLVM已经得出, NSObject都会走一个objc_alloc方法。那么继承于NSObject也会走一个objc_alloc方法。这个也是之前我们那张汇编的图片SATest, 也走了objc_alloc原因

那么问题也出现了
objc_alloccallAlloc 并不应该走
alloc_objc_rootAlloc_objc_rootAlloccallAlloc

我们在callAlloc打个断点发现, 的确是走了2次, 这就很离谱?

我们在 callAlloc跟一下流程

可看到自定义类中objc_alloc, callAlloc走的是(id, SEL))objc_msgSend)(cls, @selector(alloc));, 即向系统发送消息, 没有走_objc_rootAllocWithZone

这里我们需要再看下LLVMGeneratePossiblySpecializedMessageSend消息发送这里

我们可以看到但凡是runtime的消息发送必然现在走if判断, 由于传入sel@selector(alloc)并没有走过, 没有找到所以这里的if判断是false, 走GenerateMessageSend这个方法, 即调用selalloc方法, 即alloc_objc_rootAlloc_objc_rootAlloccallAlloc

总结:

NSObject

自定义类

举报

相关推荐

0 条评论