在我接触到的编程项目中。基本上大部分程序都是从main文件中的main方法开始执行的。
而在iOS开发中也有一个Main文件。与一般的Main文件不同的是这个文件包含有一段代码
int main(int argc, char * argv[]) {
@autoreleasepool {
return UIApplicationMain(argc, argv, nil, NSStringFromClass([AppDelegate class]));
}
}
这段代码特殊的地方在于@autoreleasepool代码块下包含的一个方法
那么这个@autoreleasepool{}有什么用呢
简单的来说这段代码可以使得在其代码块内的对象release一次。但是这个答案明显不能让作为程序员的我们的好奇心得到满足
那么我们就来仔细分析一下这其中的原理
Autorelease对象
void *context = objc_autoreleasePoolPush();
//代码块内容
objc_autoreleasePoolPop()
这两个函数都是对AutoreleasePoolPage的简单封装。所以自动释放机制的核心就是AutoreleasePoolPage这个用C++写成的对象
从给出的参数我们可以得到以下信息
1.autoreleasePoolPage没有自己的结构。是一个由若干个相同对象组成的双向链表.
2.每个AutoreleasePoolPage都有一个对应的线程。见参数pthread_t const thread.
3.每个AutoreleasePoolPage对象都会开辟一个4096字节的虚拟内存。除了上图出现的实例变量所占的空间其余都是给autorelease对象占用
4.next指向的是下一个Autorelease对象进来的虚拟内存空间地址。
5.当一个AutoreleasePoolPage满了就会开辟一个新的AutoreleasePoolPage。连接链表。新加入的autorelease对象将加入到下一个Page中去
如下图所示是一个即将满了的autoreleasePoolPage对象
每次给对象发送autorelease消息就讲对象的地址加入到next指针所在位置。当本页虚拟内存满了后开辟一个新A的AutoreleasePoolPage对象,next指针将指向新的栈底(begin)位置所在。
以上就是Autorelease加入操作
释放操作的话如下图所示
每次push进一个对象就会生成一个哨兵对象。objc_autoreleasePoolPage()返回的就是这个哨兵对象的地址。
释放的时候以哨兵对象地址为标准。从最新的page一直往前释放。即给每个对象发送-release消息。直至哨兵对象。
这就是最终释放后的样子