当前位置: 首页 > wzjs >正文

网站开发需会的课程领导高度重视门户网站建设

网站开发需会的课程,领导高度重视门户网站建设,建个人网站做导购,wordpress 插件api「OC」源码学习——alloc与init的实现 前言 费劲千辛万苦终于项目给写完了,进入下一个阶段,源码的学习 alloc的调用顺序 我们在main函数之中打上断点,先运行 再在alloc之中的各个函数之中打上断点,在关键步骤上打上断点&#…

「OC」源码学习——alloc与init的实现

前言

费劲千辛万苦终于项目给写完了,进入下一个阶段,源码的学习

alloc的调用顺序

我们在main函数之中打上断点,先运行

image-20250422120724912

再在alloc之中的各个函数之中打上断点,在关键步骤上打上断点,我们可以,很容易总结出我们alloc源码的编译流程。

先说结论,编译的具体流程如下

1487527-bc778871d88fdd22

流程探究

接下来我们在按照这个顺序进行断点调试,我们现在allocobjc_alloc处打一个断点,运行程序,我们会发现我们的断电先停在的是objc_alloc内,查看网上的资料,这是因为LLVM 在编译阶段会将 alloc 符号替换为 objc_alloc 入口点。

image-20250423114756417

接着继续步入,断点情况如下

image-20250423115300414

进入alloc流程之中的核心callAlloc,对两个return打上断点,我们可以看到,自定义类在第一次进入callAlloc的时候,是会使用消息转发的方法,再去调用真正的alloc函数

image-20250423120018851

至于为何需要走两次callAlloc的原因我们先按下不表,接着程序再次调用callAlloc,这次我们会发现断点打在了_objc_rootAllocWithZone之中

请添加图片描述

进入函数看看
image-20250423194828460

这个函数内容过于复杂,等到下一篇文章再详细阐述,我们只要知道,这个程序是动态创建类实例的核心函数,用于分配内存并初始化实例的 isa 指针。

Objective-C 中自定义类的 alloc 方法调用流程涉及双重 callAlloc 的机制,其根源在于 类初始化延迟运行时多态性设计。以下是该流程的核心原因及分步解析:

1. 首次调用 objc_alloc
  • 入口id objc_alloc(Class cls) 是运行时提供的全局分配函数。
  • 目的
    • 检查类是否已初始化(cls->isRealized())。
    • 若未初始化,触发 class_initialize() 完成类加载。
2. 进入 callAlloc
  • 参数checkNil=trueallocWithZone=false
  • 逻辑
    • 检查类是否存在(slowpath(checkNil && !cls))。
    • 若类支持优化路径(未重写 allocWithZone:),直接调用 _objc_rootAllocWithZone
3. 动态派发 objc_msgSend
  • 触发条件:若类重写了 allocWithZone:,需通过消息发送调用自定义逻辑。
  • 结果:进入类的 +alloc 方法,最终再次调用 callAlloc
4. 第二次 callAlloc
  • 参数checkNil=falseallocWithZone=true
  • 逻辑
    • 直接调用 _objc_rootAllocWithZone,跳过安全检查。
    • 最终通过 _class_createInstanceFromZone 完成内存分配和 isa 绑定。

两次进入的区别

我们现在在来看看两次进入callAlloc究竟有什么区别

第一次调用 callAlloc 时,参数 checkNil=true,在程序之中需要验证类是否存在。

image-20250424121010777

第二次调用 callAlloc 时,参数 checkNil=false,跳过安全检查。

image-20250424121031770

其实差别就在于,后面传进的两个布尔值,其实就是是否需要进行安全检查。在第一次进入callAlloc会做一次检查,确保对应的类不为空。

为何自定义类需要进入两次callAlloc

static ALWAYS_INLINE id
callAlloc(Class cls, bool checkNil, bool allocWithZone=false)
{if (slowpath(checkNil && !cls)) return nil;if (fastpath(!cls->ISA()->hasCustomAWZ())) {return _objc_rootAllocWithZone(cls, nil);}// No shortcuts available.if (allocWithZone) {return ((id(*)(id, SEL, struct _NSZone *))objc_msgSend)(cls, @selector(allocWithZone:), nil);}return ((id(*)(id, SEL))objc_msgSend)(cls, @selector(alloc));
}

系统类(如 NSObject):

因为NSObject在编译时已完成isa指针的初始化。所以不需要经过两次callAlloc

只需要直接进入objc_alloc->callAlloc->_objc_rootAllocWithZone直接申请空间即可

自定义类:

  • 第一次 callAlloc 通过 objc_alloc 进入,目的是 检查类的初始化状态,类初次创建是没有默认的alloc/allocWithZone实现的所以继续向下执行进入到msgSend消息发送流程,为这个类进行初始化。

  • 第二次 callAlloc,此时类已初始化完成,进入实际内存分配逻辑。

  • callAlloc 的分支逻辑

    if (fastpath(!cls->ISA()->hasCustomAWZ())) {return _objc_rootAllocWithZone(cls, nil); // 直接分配内存
    } else {return objc_msgSend(cls, @selector(alloc)); // 通过消息发送调用自定义逻辑
    }
    
    • hasCustomAWZ():检测类是否重写了 allocWithZone: 方法。
    • 若未重写(默认情况),直接调用 _objc_rootAllocWithZone 分配内存。
    • 若重写,则通过 objc_msgSend 触发动态派发,确保调用正确的 alloc 实现。

    那么源码是如何查看缓存的呢,我们进入hasCustomAWZ()看一下

    #   define FAST_CACHE_HAS_DEFAULT_AWZ    (1<<14)
    bool hasCustomAWZ() const {return !cache.getBit(FAST_CACHE_HAS_DEFAULT_AWZ);}bool getBit(uint16_t flags) const {return _flags & flags;}
    

    FAST_CACHE_HAS_DEFAULT_AWZ宏定义表示 是否实现alloc/allocWithZone位域标识位

    为了证明是类没有初始化的问题才导致callAlloc函数在类第一次被调用的时候被进入两次,我们可以通过在申请一次空间来尝试一下,断点和之前的一样。

    GGObject *obj = [GGObject alloc];
    GGObject *obj2 = [GGObject alloc];
    

    image-20250424141439512

    我们发现obj2的alloc调用顺序就和NSObject一样了。objc_alloc->callAlloc->_objc_rootAllocWithZone

    但紧接着问题又来了,重复进入callAlloc的原因我们找到了,那为什么要设置这个流程,这个所谓的类初始化实在哪里开始的呢?

    查看hasCustomAWZ()的调用栈可以看到,有个名字为 _objc_msgSend_uncached的方法,其实也很好理解,就是消息发送给了一个初始化信息的类之中,其实就是在消息转发这一步顺带把第一次调用的类进行初始化,然后在第二次进入hasCustomAWZ()就能进入

    _objc_rootAllocWithZone

image-20250424132737830

双重 callAlloc 流程是 Objective-C 运行时与编译器协作的产物,其核心目的是 确保类初始化完成兼容自定义内存分配逻辑。这一机制平衡了性能、灵活性与安全性,是 Objective-C 动态特性的典型体现。

init

其实点进去init, 很简单,就是把内容返回一次,如此设计的原因是为了让整个程序符合工厂模式的设计理念,我们可以通过简单的重新init的方法去实现较为复杂的其他操作。

image-20250424164807997

总结

其实我是想讲整一个alloc的流程梳理完整再将内容发出,无奈一个完完整整的流程涉及的内容实在过多,有想要了解的可以看 OC对象底层内存开辟和实现(中)了解初始化类的完整流程

参考资料

iOS-底层原理 02:alloc & init & new 源码分析

iOS-底层原理 04:NSObject的alloc 源码分析

OC对象底层内存开辟和实现(中)


文章转载自:

http://EtK2ZpDm.jxLtk.cn
http://hFozG7Nv.jxLtk.cn
http://JDnSVE6j.jxLtk.cn
http://iDNr0dK3.jxLtk.cn
http://rPd3ISqM.jxLtk.cn
http://eT8gnMgx.jxLtk.cn
http://2EjUheRO.jxLtk.cn
http://QtPLeXBo.jxLtk.cn
http://bRhGK1nc.jxLtk.cn
http://4O1ntQ0S.jxLtk.cn
http://d3VKipRZ.jxLtk.cn
http://ZtkRbBnL.jxLtk.cn
http://nbSTiQXO.jxLtk.cn
http://3IZ7E1dc.jxLtk.cn
http://AHEk7H5I.jxLtk.cn
http://8N6FZzmw.jxLtk.cn
http://RQ6UEqWv.jxLtk.cn
http://bbU5fF1L.jxLtk.cn
http://QxqOvYNS.jxLtk.cn
http://2e6GtKBM.jxLtk.cn
http://pTbuytxD.jxLtk.cn
http://DJOjlfiF.jxLtk.cn
http://cNc3cepJ.jxLtk.cn
http://xQs4AHDK.jxLtk.cn
http://xc19QEHi.jxLtk.cn
http://eLMSsUlV.jxLtk.cn
http://YH3nyAYt.jxLtk.cn
http://X3zrlMCd.jxLtk.cn
http://z8Tf7UQe.jxLtk.cn
http://uNsnfjSL.jxLtk.cn
http://www.dtcms.com/wzjs/683013.html

相关文章:

  • 网站服务器是干什么的编程软件下载手机版
  • 网站建设银行业务预约纪念币猪年纪念币预约山东青岛最新消息
  • 自己网站做搜索引擎优化做网站送商标
  • 网站改名 备案创新的广州做网站
  • 北京注册公司需要什么云南seo整站优化报价
  • 建设工程项目管理网站百度公司地址在哪里
  • 做电商网站的公司做旅游攻略比较好的网站
  • 12306网站建设贵州省建设厅实名认证网站
  • 网站须知网页设计代码三页
  • 现在还有做网站的必要吗闵行区邮编
  • 医院做网站网站开发目前用的是什么语言
  • 沧州商城网站建设个人发布房源的网站
  • 南京网站建设电话商务网站页面
  • 响应式网站怎么设置在线小程序
  • wordpress网站布置视频教程禹城建设局网站
  • 关于申请开通网站建设的请示制作网页界面工具
  • 网站建设用细节取胜银川注册公司流程和费用
  • 旅游网站设计说明新网域名查询
  • 网站搜索建设网络营销的缺点及建议
  • 网站域名在哪里看无线网被附近多个
  • 沈阳h5模板建站手工加工网
  • Dedecms手机网站源码关于网站维护的书籍
  • 这样做自己的网站asp网站安全如何做
  • 做网站不需要编程的软件网站栏目策划
  • 合肥专业做淘宝网站建设廊坊网站建设推广经验
  • 深圳装饰公司网站如何做企业网页
  • 做网站的电话阿里云虚拟主机配置wordpress
  • php免费网站空间cms 网站
  • 网站建设哪些会影响价格嘉兴公司的网站设计
  • 上海网站排名推广搭建平台畅通渠道