这是我参与更文挑战的第3天,活动详情查看: 更文挑战
前言
iOS攻城狮应该都对alloc比较熟悉,都知道是用来初始化对象的,但alloc方法是到底是如何来初始化对象的,很多人都卡在这里,因为在项目是看不底层实现的,现在我们来用探究一下,用几种方式定位到alloc方法实现所在的底层库
汇编
通过查看汇编代码可以找到对应的符号方法
打开汇编调试,然后在alloc方法打上断点

在汇编中找到objc_alloc 符号

然后加上对应的符号断点

然后跳到对应的符号断点

这里我们就可以看到alloc所在底层库libobjc.A.dylib
step into
按住control 键,再点这个

也可以找到objc_alloc

alloc 底层流程
打开源码搜索alloc { ,看到alloc底层调用了 _objc_rootAlloc 方法

再继深入

最新的都是使用的都__OBJC2,

这地方的slowpath fastPath,跟编译的设置有有关

然后 !cls->ISA()->hasCustomAWZ,没有分配指针则调用_objc_rootAllocWithZone


计算对象的大小,最小16字节

字节对齐算法,其实就是8字节对齐就是后三位抹零,就是8的倍数,也可以通过左右移动来得到(size + 7) >> 3 << 3

calloc分配内存在libmalloc源码里,需要进步进行分析
然后就是通过initIsa函数,初始化isa

然后将类与isa进行绑定

isa分为两种,一种是直接绑定了类,另一种是nonponterIsa,因为isa指针占用8位也就是64bit,避免浪费,所有isa里存了类的地址外,还存有其他,这个需要进一步研究
这样我们就在开辟了一个内存来存储我们的对象了。
init, new 做了什么
init在底层又做了什么呢

通过源码可以看出,init什么也没做,直接返回了self,所以inti只是一种设计模式,为了方便开发者重写和在初始化的时候做一些事情
那new跟alloc init 有什么区别呢
可以看出new其实就相当于alloc init,为了方便拓展传参还是尽量少使用new来初始化对象

总结
言不胜图,下面为alloc流程图

拓展
- 调用
alloc,先调用的是objc_alloc,而不是_objc_rootAlloc, 汇编那里也看到了,而且会调用两次callAlloc,这是因为调用alloc,在进行消息转发的时候,llvm第一所有的初始化方法做了拦截,被修正到了objc_alloc
下面是llvm源码中的体现,可以看出当版本号大于8.0就会调用objc_alloc

- 还有就是
NSObject的objc_alloc会在程序启动时调用一次,所以他和其他的类不太一样不会调用俩次callAlloc























![[桜井宁宁]COS和泉纱雾超可爱写真福利集-一一网](https://www.proyy.com/skycj/data/images/2020-12-13/4d3cf227a85d7e79f5d6b4efb6bde3e8.jpg)

![[桜井宁宁] 爆乳奶牛少女cos写真-一一网](https://www.proyy.com/skycj/data/images/2020-12-13/d40483e126fcf567894e89c65eaca655.jpg)