iOS 38 -- 内存关联之自动释放池
2022-01-04 本文已影响0人
恋空K
@autoreleasepool {
MJPerson *person = [[[MJPerson alloc] init] autorelease];
}
autoreleasepool 对应生成的c++代码是长这样子的
{
__AtAutoreleasePool __autoreleasepool;
MJPerson *person = ((MJPerson *(*)(id, SEL))(void *)objc_msgSend)
((id)((MJPerson *(*)(id, SEL))(void *)objc_msgSend)((id)((MJPerson *(*)(id, SEL))
(void *)objc_msgSend)((id)objc_getClass("MJPerson"), sel_registerName("alloc")),
sel_registerName("init")), sel_registerName("autorelease"));
}
也就是等价于
{
__AtAutoreleasePool __autoreleasepool;
MJPerson *person = [[[MJPerson alloc] init] autorelease];
}
最终本质就是这样子
{
atautoreleasepoolobj = objc_autoreleasePoolPush();
MJPerson *person = [[[MJPerson alloc] init] autorelease];
objc_autoreleasePoolPop(atautoreleasepoolobj);
}
也就说
@autoreleasepool {
MJPerson *person = [[[MJPerson alloc] init] autorelease];
}
变成了 {
里面声明了__AtAutoreleasePool __autoreleasepool;这样的一个局部变量(结构体变量)
}
这样的一个大括号
这是一个结构体
struct __AtAutoreleasePool {
__AtAutoreleasePool() { // 构造函数,在创建结构体的时候调用
atautoreleasepoolobj = objc_autoreleasePoolPush();
}
~__AtAutoreleasePool() { // 析构函数,在结构体销毁的时候调用
objc_autoreleasePoolPop(atautoreleasepoolobj);
}
void * atautoreleasepoolobj;
};
我们这样__AtAutoreleasePool __autoreleasepool;去定义一个结构体变量,程序运行过程中定义了
这么一个结构体变量,是不是就是相当于创建了这个结构体,一旦创建了这个结构体,也就是执行
了__AtAutoreleasePool __autoreleasepool;这行代码,那么肯定会去
执行objc_autoreleasePoolPush();这个函数,
离开 {
__AtAutoreleasePool __autoreleasepool;
MJPerson *person = [[[MJPerson alloc] init] autorelease];
} 这个大括号的时候,也就是大括号结束的时候。意味着__autoreleasepool这个结构体变量要销毁了。
因为__autoreleasepool是个局部变量,而局部变量,离开它的作用域,也就是离开它所在的大括号就会销毁。
而这个结构体一旦销毁,就会调用结构的析构函数。也就是调用
objc_autoreleasePoolPop(atautoreleasepoolobj);这个函数
所以本质就变成了这样子
{
atautoreleasepoolobj = objc_autoreleasePoolPush();
MJPerson *person = [[[MJPerson alloc] init] autorelease];
objc_autoreleasePoolPop(atautoreleasepoolobj);
}
所以我们以后看到 @autoreleasepool {
//atautoreleasepoolobj = objc_autoreleasePoolPush();
MJPerson *person = [[[MJPerson alloc] init] autorelease];
//objc_autoreleasePoolPop(atautoreleasepoolobj);
}时
在大括号开始的位置调用了atautoreleasepoolobj = objc_autoreleasePoolPush();这句代码
大括号结束的时候调用了objc_autoreleasePoolPop(atautoreleasepoolobj);这句代码
所有只要看到@autoreleasepool{ }大括号,就是被poolPush 和poolPop所包围的。所以我们要想autorelease对象什么时候调用release,什么时候销毁。只要研究开始的poolPush和结poolPop干了什么事情就好了
代码13行到16行最终变成下面了的那个大括号
_ _ AtAutoreleasePool是一个c++的结构体
poolpush和poolPop 底层调用的是AutoreleasePoolPage的push方法和pop方法
成员变量thread,应该是代表autoreleasepoolpage专属于某一个线程的
autoreleasepoolpage对象的push方法
这就是双向链表
AutoreleasePoolPage结构。每一个AutoreleasePoolPage对象都会有一定的空间用来存放调用了autorelease方法的对象的地址值。每一个AutoreleasePoolPage对象除去自身成员变量占用的空间后,还剩余4040个字节
autoreleasepool嵌套的情况
autoreleasepool嵌套的情况对应底层page的情况
先进后出
当前page