前言

前面我们使用官方开源的objc源码进行了编译调试

objc4-818.2源码编译调试笔记

前言为什么会想要调试源码? 苹果开源了部分源码, 但相似内容太多, 基本找不到代码见的对应关系, 如果能像自己工程一样进行跳转那多好哇~~苹果源码开源地址: https://opensource.apple.com/本文将以macOS 11.2/objc4-818.2的源码进行配置源码配置首先...

然后基于这份笔记, 开始探索OC的底层原理

alloc源码探索

众所周知, OC里"万物皆对象", 而这个对象则是通过alloc来创建的, 那么接下来我们就从这个点开始吧

首先创建一个类"ABC"(里面空实现), 然后在main中写上如下代码, 并在alloc那行打上断点

按⌘+r运行一下, 停在断点位置以后按下

按钮, 我们进去里面的代码看看

继续往里面走ing..

继续往里面走ing..

这里往下走ing.. (主要目的是先大概走完alloc的逻辑嘛~)

在fastpath()这个判断里面return了

这个hasCustomAWZ()是判断 是否有自定义的+allocWithZone方法实现

这里if是取反的, 所以是没有自定义的+allocWithZone方法就往if判断里面走

而自定义的+allocWithZone方法里, 瞄了一眼, 实际也是调用_objc_rootAllocWithZone()函数

我们继续往里走一下看看..

继续往里面走ing..

先记录一下调这函数的传参

cls Class ABC 0x00000001000080e8

extraBytes size_t 0

zone void * NULL 0x0000000000000000

construct_flags int 2

cxxConstruct bool true

outAllocatedSize size_t* NULL 0x0000000000000000

这里往下走看看..

可以看见, 这里是走calloc()的判断, 而这里的size是由instanceSize()计算得出的

// 计算需要开辟的内存大小, 传入的extraBytes为0

size = cls->instanceSize(extraBytes); //size=16

calloc()方法给obj对象申请了一块内存空间

继续往下走看看..

来到的是initInstanceIsa()的判断里面, 我偷偷瞄了一下里面在干啥(就简单概括了):

initInstanceIsa() -> initIsa()

// 这里的isa为objc_object结构体的私有变量, 大概意思就是--将isa和cls进行绑定

-> { newisa.setClass(cls) + isa=newisa }

回来继续往下走哈..

走到这里就直接return一个obj对象了

吓得我赶紧查了一下fastpath()这个宏函数

#define fastpath(x) (__builtin_expect(bool(x), 1)) //x很可能为真

#define slowpath(x) (__builtin_expect(bool(x), 0)) //x很可能为假

附 __builtin_expect()的作用

https://blog.csdn.net/qq_22660775/article/details/89028258

作用是"允许程序员将最有可能执行的分支告诉编译器", 即

__builtin_expect(EXP, N) 意思是:EXP==N的概率很大。



附 instanceSize()的展开

对alloc内计算大小的逻辑进行展开

fastpath()里面return了fastInstanceSize()方法, 其作用从名字上能知道: 快速计算内存大小

展开后能通过断点发现, 它进行了16字节对齐

按照对齐公式

假设: 传进去 x是10

得到: (10 + 15) & ~15

10+15=25 在二进制中表现为 0001 1001

15           在二进制中表现为 0000 1111

~15          在二进制中表现为 1111 0000

25 & ~15  在二进制中表现为 0001 0000    => 十进制中表现为 16

好家伙! 不满16的直接对齐成16了

引用百度上大佬的结论: (链接)

① 性能快 以空间换取时间

② 16字节对齐,使之有更大的容错空间

③ 会"属性重排", 进行内存优化



总结

到目前为止+alloc方法的底层逻辑如下:

+[cls alloc] //从main中的alloc方法开始

↓

_objc_rootAlloc()

↓

callAlloc()

↓

_objc_rootAllocWithZone()

↓

_class_createInstanceFromZone()

↓ //===以下是内部实现逻辑===

↓ //从这里开始是核心内容了

instanceSize() //计算需要开辟的内存空间大小

↓

calloc() //申请开辟一块内存空间并返回地址指针

↓

initInstanceIsa() //将isa和cls进行绑定

↓

return obj //返回alloc好的obj对象

↓ //===这里走出内部实现逻辑了===

↓

ABC *object //得到实例对象

通过对alloc底层源码的分析, 可以了解到: 

① alloc的主要目的是开辟内存空间;

② 主要的核心逻辑是 计算内存大小->申请内存空间->绑定isa;

③ 计算内存大小是按照16字节对齐的。





init源码探索

看完alloc源码, 总有点忍不住探索一下-init方法

直接在上面的代码里稍作修改, 打上断点, 点击运行~~\

迫不及待开始了

进去看看..

啊这... 就返回self了



总结

到目前为止-init方法的底层逻辑如下:

- [obj init]

↓

_objc_rootInit()

↓

return obj

通过对init底层源码的分析, 可以了解到: 

① 它返回了自己.. 啥都没干





new源码探索

快速开始吧

走起!

嗯..跟猜的一样



总结

到目前为止+new方法的底层逻辑如下:

+new方法 = [callAlloc() init]

通过对new底层源码的分析, 可以了解到: 

① new = [[cls alloc] init]

在以上源码中添加断点后,调试过程我总结成了一张图:\

文字流程:

+ alloc--_objc_rootAlloc--callAlloc--_objc_rootAllocWithZone--_class_createInstanceFromZone (核心实现,在方法中,完成对象大小计算,对齐,开辟,关联)

总结:\

本文为oc对象的初步探究,仅提到oc对象alloc的流程,init过程将在下一章讲述。

青山不改,绿水常流。谢谢大家!

带你领略下iOS中OC的“alloc”源代码,让你在工作中不在迷惑的更多相关文章

  1. 自动添加菜品,加入运行中遇到的异常,生成日志文件...<工作中场景...>

    """ 很弱智的小脚本,记录下.也许以后看到会笑,因为太幼稚或者证明曾经也努力过.so... """ """ ...

  2. iOS下JS与OC互相调用(五)--UIWebView + WebViewJavascriptBridge

    WebViewJavascriptBridge是一个有点年代的JS与OC交互的库,使用该库的著名应用还挺多的,目前这个库有7000+star.我去翻看了它的第一版本已经是4年前了,在版本V4.1.4以 ...

  3. iOS下JS与OC互相调用(六)--WKWebView + WebViewJavascriptBridge

    上一篇文章介绍了UIWebView 如何通过WebViewJavascriptBridge 来实现JS 与OC 的互相调用,这一篇来介绍一下WKWebView 又是如何通过WebViewJavascr ...

  4. iOS下JS与OC互相调用(四)--JavaScriptCore

    前面讲完拦截URL的方式实现JS与OC互相调用,终于到JavaScriptCore了.它是从iOS7开始加入的,用 Objective-C 把 WebKit 的 JavaScript 引擎封装了一下, ...

  5. iOS开发OC基础:Xcode中常见英文总结,OC常见英文错误

    在开发的过程中难免会遇到很多的错误,可是当看到系统给出的英文时,又不知道是什么意思.所以这篇文章总结了Xcode中常见的一些英文单词及词组,可以帮助初学的人快速了解给出的提示.多练习,就肯定能基本掌握 ...

  6. 转载 iOS js oc相互调用(JavaScriptCore) --iOS调用js

    iOS js oc相互调用(JavaScriptCore)   从iOS7开始 苹果公布了JavaScriptCore.framework 它使得JS与OC的交互更加方便了. 下面我们就简单了解一下这 ...

  7. 排版紧凑情况下IOS 浏览器的文字部分选中问题

    一.需求 一个每一项都是图文混排的列表页,在需要对其中的某一部分文字进行选中copy的时候,IOS个二货每次都是直接选中了整个列表项,无论怎么操作它的选框都没有办法做到部分选中. 这是我本周遇到遇到的 ...

  8. iOS开发——OC篇&常用关键字的使用与区别

    copy,assign,strong,retain,weak,readonly,readwrite,nonatomic,atomic,unsafe_unretained的使用与区别 最近在学习iOS的 ...

  9. iOS开发——OC篇&纯代码退出键盘

    关于iOS开发中键盘的退出,其实方法有很多中,而且笔者也也学会了不少,包括各种非纯代码界面的退出. 但是最近开始着手项目的时候却闷了,因为太多了,笔者确实知道有很多中方法能实现,而且令我影响最深的就是 ...

  10. iOS开发-OC语言 (七)继承、多态、类别

    继承.多态.类别 学习目标 1.继承的含义 2.父类子类的别称 3.字段和消息的继承 4.重写和重写消息的调用 5.多态 6.类别(Category) ======================== ...

随机推荐

  1. kubeadm 搭建 k8s 时用到的常用命令汇总

    简单记录一下 kubeadm config images list 修改镜像名称 docker tag registry.cn-hangzhou.aliyuncs.com/google_contain ...

  2. express学会CRUD

    使用express 搭建项目 1==> express 项目名 -e 2==> 然后按照提示就可以了 cd 项目名 3==>进入项目 下载依赖 cnpm i 4==>启动项目 ...

  3. vue3封装搜索表单组件

    seacrch 表单完成的功能 1.根据配置json配置项自动生成表单 ok 2.是响应式的排版 ok 3.点击搜索按钮会向上抛出值 ok 4.点击重置按钮会自动清空数据,不需要父组件额外的处理 ok ...

  4. js计算两个时间相差多少分钟

    <script> var str = "2020-02-04" console.log(str) console.log(str.replace(/-/g, " ...

  5. 超级好用的elementui动态循环菜单

    <template> <div> <el-menu @select="selectMenu" :default-active="curren ...

  6. 【k哥爬虫普法】非法入侵计算机信息系统,获取1500万余条个人信息!

    我国目前并未出台专门针对网络爬虫技术的法律规范,但在司法实践中,相关判决已屡见不鲜,K 哥特设了"K哥爬虫普法"专栏,本栏目通过对真实案例的分析,旨在提高广大爬虫工程师的法律意识, ...

  7. 什么是ChatGPT,什么是大模型prompt

    什么是ChatGpt ChatGPT是一个由美国的OpenAI公司开发的聊天机器人,它使用了大型语言模型,现在有GPT-3.GPT-3.5.GPT-4.0多个版本,目前还在快速发展,通过监督学习和强化 ...

  8. Go基础之指针

    Go语言中的指针 目录 Go语言中的指针 一.Go语言中的指针介绍 1.1 指针介绍 1.2 基本语法 1.3 声明和初始化 1.4 Go 指针的3个重要概念 1.4.1 指针地址(Pointer A ...

  9. ADB精简安卓系统:基础环境

    KMSID: 80999 是否同步到KM: 是 是否原创: 是 标签: 游戏开发 允许复制: 是 允许评论: 是 允许导出PDF: 是 职业库分类: 游戏-游戏程序 查看权限:网易正式员工-公开, 网 ...

  10. C/C++ 实现Socket交互式服务端

    在 Windows 操作系统中,原生提供了强大的网络编程支持,允许开发者使用 Socket API 进行网络通信,通过 Socket API,开发者可以创建.连接.发送和接收数据,实现网络通信.本文将 ...