objc下层c++代码
生成c++代码查看
- clang -rewrite-objc main.m -o main.cpp
- 脚本直接直接配置到测试工程里
image.png
脚本直接生成c++代码 并打开
image.png
选择脚本 build,xcode直接弹窗打开c++代码
image.png
查找autorelease相关c++代码
image.png
- 全局查找 __AtAutoreleasePool 是个结构体
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
-
如果就这样分析,还是一股脑儿就是代码,没什么直观意识,能查看到具体结构信息最好
关闭arc
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操作 分析一下
-
释放池是分页设计,就像内存分页概念一样,如果不分页,一下子要面对池子里的一坨很大的数据,人是无法处理超级多的复杂的事情的,这儿自动释放池也一样
-
不分页的设计会造成池子里对象么次操作 都需要检索整个池子,而池子对象可能很多,效率不高
-
只有分页对于栈式结构来说,每次操作只在有限长度栈结构内,超过就一页一页pop,之前被压在hot页下面的不活动页变成hot,每次操作只需要检索一小块数据对象
-
对于嵌套释放池,不分页设计就没有了渐进式内存处理,池子要么整个内存,要么整个释放,但其实从应用逻辑业务角度来看,用户的操作是一个一个访问具体功能,分页才更合理
-
自动释放池整体可以理解为两层栈结构
-
外层把一个个page看作一个个单元,page压栈出栈的过程,page大小是固定的,顶层的page为活动的page,也就是当前操作的page
-
page内部也是一个栈结构,object压栈出栈,object可能是常规对象,也可能是边界,用于区分是不是嵌套了池子
-
池子可能跨越了多个page,也可能就在一个page里,不重要,看边界在哪儿
-
分析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

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











网友评论