美文网首页
iOS 38 -- 内存关联之自动释放池

iOS 38 -- 内存关联之自动释放池

作者: 恋空K | 来源:发表于2022-01-04 17:07 被阅读0次
     @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

    相关文章

      网友评论

          本文标题:iOS 38 -- 内存关联之自动释放池

          本文链接:https://www.haomeiwen.com/subject/rnaohltx.html