OC底层探索:alloc&init

这是我参与更文挑战的第3天,活动详情查看: 更文挑战

前言

iOS攻城狮应该都对alloc比较熟悉,都知道是用来初始化对象的,但alloc方法是到底是如何来初始化对象的,很多人都卡在这里,因为在项目是看不底层实现的,现在我们来用探究一下,用几种方式定位到alloc方法实现所在的底层库

汇编

通过查看汇编代码可以找到对应的符号方法

打开汇编调试,然后在alloc方法打上断点

image.png

在汇编中找到objc_alloc 符号
image.png

然后加上对应的符号断点

image.png

然后跳到对应的符号断点

image.png

这里我们就可以看到alloc所在底层库libobjc.A.dylib

step into

按住control 键,再点这个
image.png

也可以找到objc_alloc

image.png

alloc 底层流程

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

image.png
再继深入

image.png
最新的都是使用的都__OBJC2

image.png

这地方的slowpath fastPath,跟编译的设置有有关
image.png
然后 !cls->ISA()->hasCustomAWZ,没有分配指针则调用_objc_rootAllocWithZone

image.png

image.png

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

image.png

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

image.png

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

image.png

然后将类与isa进行绑定

image.png

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

init, new 做了什么

init在底层又做了什么呢

image.png
通过源码可以看出,init什么也没做,直接返回了self,所以inti只是一种设计模式,为了方便开发者重写和在初始化的时候做一些事情

newalloc init 有什么区别呢

可以看出new其实就相当于alloc init,为了方便拓展传参还是尽量少使用new来初始化对象
image.png

总结

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

image.png

拓展

  • 调用alloc,先调用的是objc_alloc,而不是_objc_rootAlloc, 汇编那里也看到了,而且会调用两次callAlloc,这是因为调用alloc,在进行消息转发的时候,llvm第一所有的初始化方法做了拦截,被修正到了objc_alloc

下面是llvm源码中的体现,可以看出当版本号大于8.0就会调用objc_alloc

image.png

  • 还有就是NSObjectobjc_alloc 会在程序启动时调用一次,所以他和其他的类不太一样不会调用俩次callAlloc
© 版权声明
THE END
喜欢就支持一下吧
点赞0 分享