都别吵了,看了这篇iOS的OC中alloc执行原理,你什么都明白了

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

objc4-818.2源码编译调试笔记

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

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


alloc源码探索
众所周知, OC里"万物皆对象", 而这个对象则是通过alloc来创建的, 那么接下来我们就从这个点开始吧
首先创建一个类"ABC"(里面空实现), 然后在main中写上如下代码, 并在alloc那行打上断点

3555E00F556F934FFFB0EC6523


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

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

C102083A0F037E2D59491


继续往里面走ing..

3F1304E6C65C637B656224B67


继续往里面走ing..

7808B1A93D015650F947B05

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

7B7420239815E7D7D3B5E


在fastpath()这个判断里面return了
这个hasCustomAWZ()是判断 是否有自定义的+allocWithZone方法实现
这里if是取反的, 所以是没有自定义的+allocWithZone方法就往if判断里面走
而自定义的+allocWithZone方法里, 瞄了一眼, 实际也是调用_objc_rootAllocWithZone()函数
我们继续往里走一下看看..

411ADA1DCF94E21F0FEB44EFCFA


继续往里面走ing..

EB2AFE6598E9C18F1465D9


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

cls Class ABC 0x00000001000080e8

extraBytes size_t 0

zone void * NULL 0x0000000000000000

construct_flags int 2

cxxConstruct bool true

outAllocatedSize size_t* NULL 0x0000000000000000

这里往下走看看..


42245E9277B18A9992B103g


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

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

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

calloc()方法给obj对象申请了一块内存空间
继续往下走看看..

BB576EF8F3554E806C3A24


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

initInstanceIsa() -> initIsa()

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

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

回来继续往下走哈..


7236D2BFA3A5D6466F06Cg


走到这里就直接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内计算大小的逻辑进行展开

11E6E3988E4BE803B723D2932608


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

E6FB99F2CDD48141A78D512EF030g


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

2C3915F72165F0D223FB2g


按照对齐公式
假设: 传进去 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方法
直接在上面的代码里稍作修改, 打上断点, 点击运行~~

3555E00F556F934FFFB0EC65238E12E4.jpg


迫不及待开始了

C102083A0F037E2D59491CC883g


进去看看..

C9CA64CD099C65599722D11479g


啊这... 就返回self了

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

- [obj init]

↓

_objc_rootInit()

↓

return obj

通过对init底层源码的分析, 可以了解到:
① 它返回了自己.. 啥都没干


new源码探索
快速开始吧

9FBF6DC1F54FF751D3E83pg


走起!

871FAE0CAB93AE4FE61819Ag


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

+new方法 = [callAlloc() init]

通过对new底层源码的分析, 可以了解到:
① new = [[cls alloc] init]

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

imagng

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

总结:

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

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

©著作权归作者所有,转载或内容合作请联系作者
禁止转载,如需转载请通过简信或评论联系作者。
  • 序言:七十年代末,一起剥皮案震惊了整个滨河市,随后出现的几起案子,更是在滨河造成了极大的恐慌,老刑警刘岩,带你破解...
    沈念sama阅读 220,492评论 6 513
  • 序言:滨河连续发生了三起死亡事件,死亡现场离奇诡异,居然都是意外死亡,警方通过查阅死者的电脑和手机,发现死者居然都...
    沈念sama阅读 94,048评论 3 396
  • 文/潘晓璐 我一进店门,熙熙楼的掌柜王于贵愁眉苦脸地迎上来,“玉大人,你说我怎么就摊上这事。” “怎么了?”我有些...
    开封第一讲书人阅读 166,927评论 0 358
  • 文/不坏的土叔 我叫张陵,是天一观的道长。 经常有香客问我,道长,这世上最难降的妖魔是什么? 我笑而不...
    开封第一讲书人阅读 59,293评论 1 295
  • 正文 为了忘掉前任,我火速办了婚礼,结果婚礼上,老公的妹妹穿的比我还像新娘。我一直安慰自己,他们只是感情好,可当我...
    茶点故事阅读 68,309评论 6 397
  • 文/花漫 我一把揭开白布。 她就那样静静地躺着,像睡着了一般。 火红的嫁衣衬着肌肤如雪。 梳的纹丝不乱的头发上,一...
    开封第一讲书人阅读 52,024评论 1 308
  • 那天,我揣着相机与录音,去河边找鬼。 笑死,一个胖子当着我的面吹牛,可吹牛的内容都是我干的。 我是一名探鬼主播,决...
    沈念sama阅读 40,638评论 3 420
  • 文/苍兰香墨 我猛地睁开眼,长吁一口气:“原来是场噩梦啊……” “哼!你这毒妇竟也来了?” 一声冷哼从身侧响起,我...
    开封第一讲书人阅读 39,546评论 0 276
  • 序言:老挝万荣一对情侣失踪,失踪者是张志新(化名)和其女友刘颖,没想到半个月后,有当地人在树林里发现了一具尸体,经...
    沈念sama阅读 46,073评论 1 319
  • 正文 独居荒郊野岭守林人离奇死亡,尸身上长有42处带血的脓包…… 初始之章·张勋 以下内容为张勋视角 年9月15日...
    茶点故事阅读 38,188评论 3 340
  • 正文 我和宋清朗相恋三年,在试婚纱的时候发现自己被绿了。 大学时的朋友给我发了我未婚夫和他白月光在一起吃饭的照片。...
    茶点故事阅读 40,321评论 1 352
  • 序言:一个原本活蹦乱跳的男人离奇死亡,死状恐怖,灵堂内的尸体忽然破棺而出,到底是诈尸还是另有隐情,我是刑警宁泽,带...
    沈念sama阅读 35,998评论 5 347
  • 正文 年R本政府宣布,位于F岛的核电站,受9级特大地震影响,放射性物质发生泄漏。R本人自食恶果不足惜,却给世界环境...
    茶点故事阅读 41,678评论 3 331
  • 文/蒙蒙 一、第九天 我趴在偏房一处隐蔽的房顶上张望。 院中可真热闹,春花似锦、人声如沸。这庄子的主人今日做“春日...
    开封第一讲书人阅读 32,186评论 0 23
  • 文/苍兰香墨 我抬头看了看天上的太阳。三九已至,却和暖如春,着一层夹袄步出监牢的瞬间,已是汗流浃背。 一阵脚步声响...
    开封第一讲书人阅读 33,303评论 1 272
  • 我被黑心中介骗来泰国打工, 没想到刚下飞机就差点儿被人妖公主榨干…… 1. 我叫王不留,地道东北人。 一个月前我还...
    沈念sama阅读 48,663评论 3 375
  • 正文 我出身青楼,却偏偏与公主长得像,于是被迫代替她去往敌国和亲。 传闻我的和亲对象是个残疾皇子,可洞房花烛夜当晚...
    茶点故事阅读 45,330评论 2 358

推荐阅读更多精彩内容