带你领略下iOS中OC的“alloc”源代码,让你在工作中不在迷惑
前言
前面我们使用官方开源的objc源码进行了编译调试
前言为什么会想要调试源码? 苹果开源了部分源码, 但相似内容太多, 基本找不到代码见的对应关系, 如果能像自己工程一样进行跳转那多好哇~~苹果源码开源地址: 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”源代码,让你在工作中不在迷惑的更多相关文章
- 自动添加菜品,加入运行中遇到的异常,生成日志文件...<工作中场景...>
""" 很弱智的小脚本,记录下.也许以后看到会笑,因为太幼稚或者证明曾经也努力过.so... """ """ ...
- iOS下JS与OC互相调用(五)--UIWebView + WebViewJavascriptBridge
WebViewJavascriptBridge是一个有点年代的JS与OC交互的库,使用该库的著名应用还挺多的,目前这个库有7000+star.我去翻看了它的第一版本已经是4年前了,在版本V4.1.4以 ...
- iOS下JS与OC互相调用(六)--WKWebView + WebViewJavascriptBridge
上一篇文章介绍了UIWebView 如何通过WebViewJavascriptBridge 来实现JS 与OC 的互相调用,这一篇来介绍一下WKWebView 又是如何通过WebViewJavascr ...
- iOS下JS与OC互相调用(四)--JavaScriptCore
前面讲完拦截URL的方式实现JS与OC互相调用,终于到JavaScriptCore了.它是从iOS7开始加入的,用 Objective-C 把 WebKit 的 JavaScript 引擎封装了一下, ...
- iOS开发OC基础:Xcode中常见英文总结,OC常见英文错误
在开发的过程中难免会遇到很多的错误,可是当看到系统给出的英文时,又不知道是什么意思.所以这篇文章总结了Xcode中常见的一些英文单词及词组,可以帮助初学的人快速了解给出的提示.多练习,就肯定能基本掌握 ...
- 转载 iOS js oc相互调用(JavaScriptCore) --iOS调用js
iOS js oc相互调用(JavaScriptCore) 从iOS7开始 苹果公布了JavaScriptCore.framework 它使得JS与OC的交互更加方便了. 下面我们就简单了解一下这 ...
- 排版紧凑情况下IOS 浏览器的文字部分选中问题
一.需求 一个每一项都是图文混排的列表页,在需要对其中的某一部分文字进行选中copy的时候,IOS个二货每次都是直接选中了整个列表项,无论怎么操作它的选框都没有办法做到部分选中. 这是我本周遇到遇到的 ...
- iOS开发——OC篇&常用关键字的使用与区别
copy,assign,strong,retain,weak,readonly,readwrite,nonatomic,atomic,unsafe_unretained的使用与区别 最近在学习iOS的 ...
- iOS开发——OC篇&纯代码退出键盘
关于iOS开发中键盘的退出,其实方法有很多中,而且笔者也也学会了不少,包括各种非纯代码界面的退出. 但是最近开始着手项目的时候却闷了,因为太多了,笔者确实知道有很多中方法能实现,而且令我影响最深的就是 ...
- iOS开发-OC语言 (七)继承、多态、类别
继承.多态.类别 学习目标 1.继承的含义 2.父类子类的别称 3.字段和消息的继承 4.重写和重写消息的调用 5.多态 6.类别(Category) ======================== ...
随机推荐
- [转帖]Redis 使用指南:深度解析 info 命令
https://www.cnblogs.com/hwpaas/p/9442410.html Redis 是一个使用 ANSI C 编写的开源.基于内存.可选持久性的键值对存储数据库,被广泛应用于大型 ...
- Nginx反向代理总结
反向代理的种类 1. LVS的方案 2. DNS轮询的方案 3. Nginx的4层代理 4. Nginx的7层代理 5. 网络NAT的处理 Nginx的反向代理-四层` 编译时增加 --with-st ...
- AIGC的隐私安全问题及隐私保护技术
作者:京东科技 杨博 ChatGPT 才出现两个月,就已经引起了学术界的关注.微软成为ChatGPT母公司OpenAI的合作伙伴,并确认投资百亿美元.同时,微软正计划将 OpenAI 的技术整合到其产 ...
- TS声明promise返回来的数据类型
promise返回来的数据类型 interface backResult{ code: number, data: { name:string,age:number}[], //数组里面的对象类型,这 ...
- linux虚拟机固定ip
1.查看宿主机IP信息 在windows宿主机上,键盘输入win+r,输出cmd,打开终端命令行: 输入ipconfig /all,查看宿主机IP信息: 2.修改Linux虚拟机的配置文件 Linux ...
- P7036 [NWRRC2016] Folding
题目简述 有两个矩形,大小分别是 \(W \times Y\) 和 $ w \times y$.现在我们要通过折叠将两个矩阵变成一样. 思路 part1 已知一条边折叠一次会变成 \(\frac{x} ...
- 1.6 编写双管道ShellCode
本文将介绍如何将CMD绑定到双向管道上,这是一种常用的黑客反弹技巧,可以让用户在命令行界面下与其他程序进行交互,我们将从创建管道.启动进程.传输数据等方面对这个功能进行详细讲解.此外,本文还将通过使用 ...
- 4.0 Python 变量与作用域
在python中,变量的作用域决定了变量在哪些位置可以被访问.一个程序中的变量并不是所有的地方都可以访问的,其访问权限决定于变量的赋值位置.python中有两种最基本的变量作用域:局部作用域和全局作用 ...
- Python下的三维建模和可视化
本文介绍基于AnyCAD Rapid Py三维图形平台开发Python的三维应用 1 准备工作 1.1 安装 vc_resit 2022 在Windows下,AnyCAD Rapid SDK依赖Vis ...
- Windows XP Professional with Service Pack 3 (x86)
Windows XP Professional with Service Pack 3 (x86) 链接:https://pan.baidu.com/s/1p99vLx5psoq9K4ONlRpkZA ...