[iOS底层]-autoreleasepool底层原理
[iOS底层]-autoreleasepool底层原理
autoreleasepool的基本原理
下载Demo,通过使用Clang编译器把OC文件编译成C++文件的学习,我们已经知道如何把OC编译成C++。接下来就把main.m
编译成main.cpp
,得到@autoreleasepool
的C++的底层源码:
int main(int argc, char * argv[]) { |
可以很直观的看出,autoreleasepool
被解析成一个代码块{ }
,并且创建了一个__AtAutoreleasePool __autoreleasepool;
结构体。
struct __AtAutoreleasePool { |
autoreleasepool原理如下:
- 放在autoreleasepool中的变量和方法都是在一个局部作用域中执行。
- 这个局部作用域中第一行会先创建一个
__AtAutoreleasePool
结构体对象,这个时候会调用结构体初始化方法__AtAutoreleasePool()
,进行objc_autoreleasePoolPush
。 - 等作用域所有代码执行完毕,作用域进行销毁,此时
__AtAutoreleasePool
结构体对象也会销毁,调用析构方法~__AtAutoreleasePool()
,执行objc_autoreleasePoolPop
。
objc_autoreleasePoolPush方法分析
// objc_autoreleasePoolPush调用了AutoreleasePoolPage的push方法 |
objc_autoreleasePoolPush
调用的是AutoreleasePoolPage
类的push
方法,找到AutoreleasePoolPage
定义的地方,可以看到注释部分,苹果对Autorelease pool的实现做了一个说明:
- autoreleasepool是一个栈结构的指针集,其中存储是要释放的对象,或者是一个表示边界的哨兵对象
POOL_BOUNDARY
- 当
pool
进行pop
操作的时候,遇到了POOL_BOUNDARY
,表示对象都释放完了。 - 栈存储在
page
中,page
和page
之间通过双向链表进行连接。 - 当前操作的页会标识为
hot page
,并且线程会进行存储。
AutoreleasePoolPage结构
struct AutoreleasePoolPageData |
AutoreleasePoolPage
继承自AutoreleasePoolPageData
,AutoreleasePoolPageData
的定义如上所示:
- magic用来校验AutoreleasePoolPage的结构是否完整
- next指向新添加的autoreleased对象的下一个位置,初始化时指向begin();
- thread指向当前线程
- parent指向父节点,第一个结点的parent值为nil
- child指向子结点,最后一个结点的child为nil
- depth代表深度,从0开始,往后递增1
- hiwat代表最大入栈数量标记
objc_autoreleasePoolPush流程
根据push
方法的源码,可以得出下列调用流程图
可以得出下面的结构图
- page和page之间是双向链表链接,首页的
parent = nil
,尾页的child = nil
。 - 每个page内部都是栈结构,首页栈底是
POOL_BOUNDARY
,然后往栈里push销毁对象。 - 当前page设置为
hotPage
,next
表示hotPage
的栈顶,用来标识下次push的位置。
objc_autoreleasePoolPop方法分析

- 先找到当前边界stop标志
- 循环销毁对象
- 通过hotPage找到当前page,判断page是否为空,为空表示当前页的待销毁对象已经销毁完毕,继续找parent page的待销毁对象。
- 通过
next
找到待销毁对象,然后进行销毁。 - 遇到stop标识表示所有对象都已经销毁。
本博客所有文章除特别声明外,均采用 CC BY-NC-SA 4.0 许可协议。转载请注明来自 雷军的博客!