美文网首页
内存管理

内存管理

作者: 晨阳Xia | 来源:发表于2020-11-26 18:21 被阅读0次

    重要笔记

    1. ARC中不捕获异常的原因!
    2. MRC中不捕获异常的原因!

    第 29 条 理解引用计数

    引用计数的工作原理

    在引用计数的架构下,对象有个计数器,用以表示当前有多少个事物想令此对象继续存活下去。这在Objective-C中就叫做“保留计数”。
    NSObject协议声明了三个方法用以操作计数器

    • Retain
    • release
    • autorelease

    第 31 条 在delloc方法中只释放引用并解除监听

    绝不能自己调用delloc

    应该在delloc中做些什么呢?

    1. 主要就是释放对象所拥有的引用,也就是把所有Objective-C对象都释放掉,ARC会通过自动生成的.cxx_destruct方法,在delloc中为你自动添加这些释放代码。对象所拥有的其他非Objective-C对象也要释放。比如CoreFoundation对象就必须手工释放,因为他们都是由纯C的API生成的。
    2. 清理观察则
    -(void)delloc {
      CFRelase(coreFoundationObject);
      [[NSNotificationCenter defaultCenter] removeObserve:self];
    }
    

    如果是MRC中需要调用 [super delloc], ARC会自动执行此操作。

    delloc注意事项

    1. 虽说应该与delloc中释放引用,但是开销较大或系统内稀缺的字眼则不在此列。像是文件描述(file descriptor)、套接字(socket)、大块内存等,都属于这种资源。不能指望delloc方法必定会在某个特定的时机随机调用,因为有一些无法预料的东西也持有此对象,在这种情况下,如果非等到系统调用delloc方法是才释放,那么保留这些需缺资源的时间就有写过长了,这么做不合适。通常的做法是,实现另一个方法,当应用程序用完资源对象后,就调用此方法,这样一来,资源对象的生命周期就变的更为明确了。

    2. 在极个别情况下,当应用程序终止时,仍有对象处于存活状态,这些对象没有收到delloc消息。由于应用程序终止之后,其占用的资源也会返还给操作系统,所以实际上这些对象也就等于消亡了。不调用dealloc方法是为了优化程序效率。而这也说明系统未必会在每个对象上调用delloc方法。

    3. 如果对象管理者某些资源,那么在dealloc中也要调用“清理方法”,以防开发者忘了清理这些资源。忘记清理资源的情况经常发生,所以最好能输出一行消息,提示程序员代码里含有变成错误。在系统回收对象之前,必须调用close以释放其资源,都则close方法就失去意义了,因此,没有适时调用close方法就是编程错误。输出错误消息可促进开发者纠正次问题。而且,在程序员忘记调用close的情况下,我们应该在dealloc中补上这次调用,以防泄漏内存。如下:

      -(void)close {
         /* clean up resourse */
         _closed = YES
      }
      
      -(void)delloc {
         if (!_closed) {
           NSLog(@"ERROR: close was not called before dealloc");
           [self close]; // 调用这句话是为了侦测变成错误而破例,无论这里调
           用什么方法都不太应该。如果在这里所调用的方法又要异步执行某些任务,
           或是又要继续调用他们自己的某些方法,那么等到那些任务执行完毕时,系
           统已经把当前这个带回收的对象彻底摧毁了。这回导致很多问题,且经常使
           应用程序崩溃,因为那些任务执行完毕后,要回调此对象,告诉该对象任务
           已完成,而此时如果对象已摧毁,那么回调操作就会出错。
         }
      }
      
    4. 调用delloc方法的那个线程会执行“最终的释放操作”(final release),令对象的保留计数将为0,而某些方法必须在特定的线程里(比如主线程)调用才行。若在delloc里调用了哪些方法,则无法保证当前这个线程就是哪些方法所需要的线程。通过编写常规代码的方式,无论如何都没办法保证其会安全运行在正确的线程上,因为对象处于“正在回收的状态”(dellocating state),为了指明此状况,运行期系统已经改动了对象内部的数据结构。

    5. 在delloc里也不要调用属性的存取方法,因为有人可能会覆写这些方法,并与其中做一些无法再回收阶段安全执行的操作。此外,属性可能正处于“简直观测”(Key-Value Observation, KVO)机制的监控之下,该属性的观察者(observer)可能会在属性值改变时“保留”或使用这个即将回收的对象。这种做法会令运行期希同的状态完全失调,从而导致一些莫名其妙的错误。

    要点

    • 在delloc方法里,应该做的事情就是释放指向其他对象的引用,并取消原来订阅的“简直观测”(KVO)或NSNotificationCenter等通知,不要做其他事情。
    • 如果对象持有文件描述符等系统资源,那么应该专门编写一个方法来释放此种资源。这样的类药喝起使用者约定:用完资源后必须调用close方法。
    • 执行异步任务的方法不应在dealloc里调用:只能在正常状态下执行的那些方法也不应在delloc里调用,因为此对象已处于正在回收的状态了。

    相关文章

      网友评论

          本文标题:内存管理

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