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
上一篇下一篇

猜你喜欢

热点阅读