一、alloc、init、new源码笔记

本文由快学吧个人写作,以任何形式转载请表明原文出处。

一、需要的资料

objc4-876,地址 : github.com/apple-oss-d...

二、探索的思路

1、要探索alloc和init和new具体做了什么,就需要知道什么时候我们用alloc和new,这个很容易,OC中一个对象的初始化最常用的就是 \[Obj alloc init]和Obj new,所以,第一步我们需要一个类,并且初始化一个对象。

2、要看alloc、init和new分别做了什么,就需要把它们分开来看。

3、我们最常用也是最基本最常见的类就是NSObject,我们创建的一些基本的类大多都继承于它,所以我们以NSObject的alloc、init和new方法来探索。

3、找到NSObject的源码,进行探索。

三、需要的基本知识储备

字节对齐 :

1、为什么要字节对齐

因为苹果官方要求的。

2、为什么要这么要求

不止是苹果官方,几乎所有的语言,都会要求内存对齐。

如下图 :

首先,我们存储数据的目的不是单纯的存储,而是要在需要的时候可以调用,而cpu是不是以字节为单位来读取数据的,而是以"块"为单位。

如果所有申请内存空间的数据都要这样去申请,并且拿到不同大小的内存空间去使用。

那么在我们再调用这些数据的时候,cpu要不断的变换读取数据的内存长度大小,来精准的获取数据,这是很浪费资源的行为。

所以,字节对齐,实际上是一种以空间换取时间的方式,让cpu更高效的读取内存中的数据。

3、iOS的字节对齐

iOS的字节对齐是以16字节为基本数,开辟内存空间的大小需要是16的整数倍。

为什么iOS要以16字节进行字节对齐?

因为OC对象中,第一位一定有一个isa指针,而isa指针的大小就是8字节,如果仅仅以8字节进行字节对齐,如果两个对象都是没有其他任何属性的对象(仅仅有isa指针),那么这两个对象的内存空间就会挨在一起,就容易造成数据的混乱。

iOS也有对8字节对齐的要求,具体的详情在下面的苹果官方字节对齐算法代码那里有解释。

4、苹果官方的字节对齐算法

c 复制代码
static inline size_t align16(size_t x) {
    return (x + size_t(15)) & ~size_t(15);
}

四、alloc

1、alloc方法的跳转

1、打开准备的资料 : objc4-876的文件。

2、在Xcode的Navigators搜索alloc {,因为方法的实现都是以 { 来开始的,所以带上 { 可以省略很多麻烦。

3、在NSObject.mm文件找到 alloc的实现方法。.mm格式文件是为了支持C++和OC的混编。

4、进入_objc_rootAlloc方法。

5、进入callAlloc方法。

到这里我们可以发现,alloc的实现方法,一定是在callAlloc中提到的_objc_rootAllocWithZone或者allocWithZone方法。

如果可以断点调试的话,可以发现,实际上JDPersonalloc方法进入的是第二个if,也就是fastpath的判断里面,进入了_objc_rootAllocWithZone方法。

2、alloc的核心实现

1、在搜索栏搜索_objc_rootAllocWithZone(找到方法的实现。

2、进入_class_createInstanceFromZone方法。

这里保留一下传入的参数,以便探索。这里可以进入一下OBJECT_CONSTRUCT_CALL_BADALLOC,这个参数看一下,发现是一个枚举值,是2。所以传入的参数就是(cls, 0, nil, 2)。

3、_class_createInstanceFromZone方法的实现

3、alloc申请内存中的一些细节

1、如何计算申请内存的对象所需内存空间的大小?

这一步在_class_createInstanceFromZone方法中进行了实现,看上图中的

ini 复制代码
size = cls->instanceSize(extraBytes);

这里的size就是所需内存空间的大小,计算所用到的方法是instanceSize。直接进入instanceSize方法。

2、计算内存大小

重点在fastInstanceSizealignedInstanceSize

fastInstanceSize重点在align16 :

alignedInstanceSize重点在word_align :

3、align16word_align的源码

就是字节对齐的算法代码。

这里有一点,两个字节对齐的算法,一个是8字节对齐,一个是16字节对齐。

原因是8字节对齐的受众是对象内部的属性,对象内部的属性需要遵循8字节对齐的原则,而16字节对齐的受众则是对象。

比如 : obj1和obj2之间需要满足16字节对齐,而obj1的内部属性attr1和attr2需要满足8字节对齐。

五、init

和alloc同样,在objc4-876源码中找init的实现,在Xcode的Navigators搜索init {,找到NSObject.mm文件中的init实现。

类方法直接返回self,没有做任何的操作。实例方法调用_objc_rootInit,看一下 :

一样直接返回self。

其实init的意义在官方的注释中已经表达清楚了,init就是工厂模式,为了给开发者在实际的应用中提供一个自己可以自定义的接口。

六、new

源码查找方法同上。

new直接调用了callAlloc方法,和alloc的区别就是alloc调用的是_objc_rootAlloc方法,然后又_objc_rootAlloc调用的callAlloc,再就是传递的最后一个形参不一样。
new会直接调用init方法,如果我们自己定义一些init的方法,类似于initWith之类的,new只会调用init,而不会调用我们的init方法,所以用的比较少。

七、总结

1、alloc申请内存,字节对齐,绑定isa,核心方法是callAlloc(实际入口),instanceSize(计算开辟内存的大小),calloc(申请内存,返回地址指针),initIsa(绑定isa)。

2、init提供重写的机会,给开发者根据自身情况做自定义。

3、new直接调用了alloc的实际入口callAlloc方法,然后调用了init方法。不会调用我们自定义的一些类似于initWith的方法。

相关推荐
黑化旺仔1 天前
【OC】KVO
macos·ios·objective-c·cocoa
HouWan1 天前
SwiftUI 小技巧:如何读取 SwiftUI Font 的详细信息
ios·swiftui·apple
李游Leo1 天前
HarmonyOS 7 实战开发 05:把页面做到可上线状态
ios·harmonyos
终端安全笔记1 天前
描述文件、企业证书、MDM 不是三个名字,是三层
android·ios·智能手机
传奇开心果编程1 天前
【SwiftUI入门练中学】第1课 从零开始
学习·ui·ios·swiftui·swift
丿Wayne1 天前
iOS Token 刷新实战(Actor 避免并发重复刷新)
ios·swift·token·actor·swift并发
终端安全笔记2 天前
iOS 27 给了租赁一个新工具,但它只认受监督的设备
android·网络·安全·ios
大熊猫侯佩2 天前
独立 App 首发完成 iPhone Duo 展开态适配
ios·swiftui·swift
光影少年2 天前
setImmediate 和 setTimeout(0) 的区别
android·前端·react.js·ios·前端框架
2501_916008892 天前
SSE 和 gRPC 流式接口如何抓包,调试 SSE 与 gRPC 流式接口
网络协议·计算机网络·网络安全·ios·adb·https·udp