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


NSObject , alloc方法里面 加断点, 运行我们会发现竟然没有走+ (id)alloc方法
那么NSObject在走的是哪个方法呢?
打开 Debug→Debug 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_alloc → callAlloc 并不应该走
alloc→_objc_rootAlloc→_objc_rootAlloc→callAlloc
我们在callAlloc打个断点发现, 的确是走了2次, 这就很离谱?

我们在 callAlloc跟一下流程

可看到自定义类中objc_alloc, callAlloc走的是(id, SEL))objc_msgSend)(cls, @selector(alloc));, 即向系统发送消息, 没有走_objc_rootAllocWithZone
这里我们需要再看下LLVM中 GeneratePossiblySpecializedMessageSend消息发送这里

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

自定义类










