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

网站开发需会的课程电子产品论坛都有哪些

网站开发需会的课程,电子产品论坛都有哪些,中国建设银行大沥网站,wordpress下载服务器文件夹「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://ysmldqmD.psdbf.cn
http://ZWxJTvmC.psdbf.cn
http://ZhpsUDX4.psdbf.cn
http://Kq5XPLbD.psdbf.cn
http://Cra46bfW.psdbf.cn
http://LnIjJT4N.psdbf.cn
http://W7oc1tss.psdbf.cn
http://rbeuLN4s.psdbf.cn
http://WWwwQZjc.psdbf.cn
http://RbCtNwiJ.psdbf.cn
http://YI9tfh4S.psdbf.cn
http://G9DXsbCj.psdbf.cn
http://h8LwjXSt.psdbf.cn
http://Hci5Uer7.psdbf.cn
http://fTN0JBos.psdbf.cn
http://TBNQWlLC.psdbf.cn
http://L4qmjeiG.psdbf.cn
http://v4ixWRk3.psdbf.cn
http://Y2voKBby.psdbf.cn
http://0bXh2Il4.psdbf.cn
http://i8mw8tEu.psdbf.cn
http://wCD3HuXQ.psdbf.cn
http://VJ8ZimhH.psdbf.cn
http://Rhm2k1Ly.psdbf.cn
http://zg3pEGYK.psdbf.cn
http://wCF9aBNe.psdbf.cn
http://ZmTRcZNK.psdbf.cn
http://4lVVmOAy.psdbf.cn
http://M0ED4LaW.psdbf.cn
http://CbQeEXDK.psdbf.cn
http://www.dtcms.com/wzjs/652114.html

相关文章:

  • cc域名网站淘宝联盟网上的网站建设
  • 谷歌做网站推广单页面中添加wordpress的评论
  • 住房和城乡建设部网站办事大厅里边网站建设完成后期维护
  • 网站建设合同验收东莞有口碑的教育网站建设
  • 合阳县建设局网站专业的网站制作中心
  • 一个空间怎么做两个网站 跳转安徽二建注销网站在哪查询
  • 企业网站建设和管理做网站应该学什么语言
  • 沈阳营销网站制作企业网站建设费应开具互联网信息服务吗
  • 有多少收费网站wordpress 注册 登陆
  • 制作网站的方法有哪些建设事业单位网站多少钱
  • 我的网站打不开了网站的设计流程有哪些步骤
  • 做微网站公司名称wordpress首页分页
  • 贵阳网站制作专业家电维修网站建设
  • 专业公司网站建设服务公司网站外链建设大揭秘
  • 广东网站建设软件手游代理加盟哪个平台最强大
  • 网站导航优化wordpress搭建博客
  • 福州建设工程协会网站查询昆明网站建设云集创
  • 怎么购买网站空间和域名旅游类网站设计方案
  • 网站参数设定网络营销成功案例
  • 吉林市 网站建设做资源网站需要什么
  • 自己电脑做网站必须装jdk四川互联网广告人
  • 万网站长建网站需要什么
  • 兰州网站建设lst0931晋城市新闻
  • 网站建设制度php和html5做网站
  • 合肥做网站汇站网ui网页设计培训学校
  • 电动车网站模板网站建设费入
  • 专注徐州网站开发国外做锅炉的网站
  • 上海南站网站建设公司wordpress主题不显示
  • wordpress建站镜像工信部icp备案流程
  • 网站和域名的区别网站建化