ios底层原理

自动释放池

2022-06-20  本文已影响0人  erlich

objc下层c++代码

生成c++代码查看

image.png

脚本直接生成c++代码 并打开


image.png

选择脚本 build,xcode直接弹窗打开c++代码


image.png

查找autorelease相关c++代码

image.png
image.png

其实说白了就是结构体(自动释放池)构造,析构

其实说白了就是结构体(自动释放池)构造,析构

image.png

构造 objc_autoreleasePoolPush() 压栈

析沟 objc_autoreleasePoolPop(void *) 弹出栈

根据c++代码分析大致了解到,自动释放池其实就是一块作用域时机,作用域开始时构造,作用域结束时析构回收 主要是个栈结构

汇编查看

image.png
image.png

通过汇编,结果更直观,压栈,执行逻辑, 出栈

汇编 进入符号 objc_autoreleasePoolPush 最终得到符号所在的dyld

image.png

发现 objc_autoreleasePoolPush 符号存在于objc源码中,所以我们进入源码

没有源码环境?快速配置一个出来

打开源码调试工程

查找符号 objc_autoreleasePoolPush

image.png
image.png
image.png

既然提到了打印信息,那么就看源码里有没有相关的调试打印函数,既然有调试,应该会有,拿来用就可以了

前后多看些范围代码,发现了打印函数

image.png

既然C函数,我们可以声明extern来使用

image.png
image.png
image.png
image.png
image.png
image.png

非arc下,autorelease - 对象才会放入池子

image.png
image.png
image.png
image.png

这时候 其实可以看出关键点了 根据打印逻辑回看源码

AutoreleasePoolPage: AutoreleasePoolPageData

image.png

可以看出是个双向链表 (nil <- page <-> page <-> page <-> page -> nil)

image.png

AutoreleasePoolPage: push()

image.png
image.png
image.png
image.png

释放池push操作 分析一下

分析page大小

根据上面的1024次循环 构建1024个对象,打印结果出现两次 page full标识,也就是有3页,两个满页

hot page未满,有15个对象

也就是说每个page ((1024-15) + 1) / 2 = 505 个对象(每个对象指针8字节)【+1是因为还有一个边界8字节】

505 * 8 = 4040字节 ---- 4k == 4096字节 ----- 差56字节? 差在了哪儿?

image.png
image.png

可以理解为 每个page有一个magic_t 结构的头,占用16字节 page大小4k得证

自动释放池嵌套

image.png image.png image.png
image.png

自动释放池扩展

image.png

没有autorelease,对象并没有进入释放池 当前是在非ARC下

现在切回ARC

image.png

其实 alloc new copy multablecopy相关前缀 在llvm编译期间不会加入到释放池

自动释放池 pop操作与push相反,就不赘述了, 简单来讲就是 从hotpage开始遍历release对象,然后page->parent 找到code page设置为hot page,当前hotpage kill

上一篇下一篇

猜你喜欢

热点阅读