zoukankan      html  css  js  c++  java
  • autoreleasepool的笔记


    1、autoreleasepool总是会被问到,放在自动释放池中的对象合适被释放?理解不正确的答案:{}出了大括号、出了作用域等等。个人认为参考答案是,1、在不是手动添加的AutoreleasePool时,当前的runloop结束时释放,因为编译器在每个runloop中开始时加入了自动释放池的Push和结束时加入了Pop;2、如果是手动添加的AutoreleasePool,就是在@autorelease{}大括号的时候释放,因为编译器在大括号之后调用的Pop。
     下面有一个例子:
    以上是测试代码。
    在ios8以下的运行结果是:

    这个运行结果也说明了“出了作用域对象就被释放的说法是不正确的”,同时也能发现,对象在viewWillAppear中还没有被释放,而到了viewDidAppear中的时候对象已经被释放了。

    再补一张证明确实是在这两个方法之间被释放的图:

    我在viewDidLoad讲要结束的时候设置了一个断点,并且在console中设置了对reference变量值变化的监听。当开始继续执行代码,并且改变reference的值时,上图展示了改变的时间点。从图中可以看到,在viewWillAppear之后reference的值被改为了nil,也就是在viewWillAppear之后自动释放池地方了对象。

    注:刚在上面写了在ios8之前的结果,因为从ios9开始编译器对NSString的stringWithFormat方法做了改变(优化),下面附一张ios9的结果图:

    2、上一条中提到的Autorelease调用Push和Pop

         
    上图中展示的是AutoreleasePoolPage的结构图,AutoreleasePool是由若干个AutoreleasePoolPage以双向链表组合而成的。每个AutoreleasePoolPage占有空间的大小是虚拟内存一页的大小(4096bytes字节)
    magic:用来校验AutoreleasePoolPage结构的完整性
    next:最新添加的autoreleased对象的下一个位置
    thread:当前的线程
    parent:指向父结点
    child:指向子结点
    depth:代表深度,从0开始向后递增1
    hiwat:high water mark
    当next == begin(),表明AutoreleasePoolPage为空;当next == end(),表明AutoreleasePoolPage已满,如下图:
    当AutoreleasePoolPage满了之后,就会建立下一个AutoreleasePoolPage对象,新的AutoreleasePoolPage的next指针被初始化在栈底(begin()的位置)。
     
    嵌套的AutoreleasePool
         前面只介绍了添加对象的情况,下面说一下释放的时刻:
         每当进行一次objc_autoreleasePoolPush时,runtime向当前的AutoreleasePoolPage中add一个哨兵对象,值为0(nil),效果如下图:
    objc_autoreleasePoolPush的返回值是这个哨兵对象的地址,于是在释放的过程中;
         1、根据传入的哨兵对象地址找到哨兵对象所在的AutoreleasePoolPage
         2、在当前AutoreleasePoolPage中,将晚于哨兵对象加入的所有对象发送release消息(可以跨越page),然后移动next指针到正确的位置
         所以知道了AutoreleasePool释放对象的过程之后,嵌套的AutoreleasePool就好理解多了,多层的AutoreleasePool就是对个哨兵对象,每次pop的时候释放上次push的位置(哨兵对象的位置)。
         
     
    3、Autorelease的其他
          在ARC中使用@autorelease{}时,编译器将  @autorelease{}转化成:
         void *context = objc_autoreleasePoolPush();
         //{}中的代码
           objc_autoreleasePoolPop(context);//如果不是手动添加的autoreleasePool,就是在当前runLoop结束时调用
         objc_autoreleasePoolPush()是对AutoreleasePoolPage::push()的封装
         objc_autoreleasePoolPop() 是对AutoreleasePoolPage::pop()的封装
     
    参考:http://www.cocoachina.com/ios/20141031/10107.html
  • 相关阅读:
    20191024-1 每周例行报告
    20191017-1 每周例行报告
    20191010-2 每周例行报告
    梁梦瑶 20190919-4 单元测试
    交换机配置VLAN Cisco packet
    20191128-1 总结
    20191121-1 每周例行报告
    20191114-1 每周例行报告
    对组内成员的感谢博客
    每周例行报告
  • 原文地址:https://www.cnblogs.com/lujianwenance/p/5702782.html
Copyright © 2011-2022 走看看