美文网首页
内存管理

内存管理

作者: 晨阳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里调用,因为此对象已处于正在回收的状态了。

相关文章

  • iOS内存管理详解

    目录 block内存管理 autorelease内存管理 weak对象内存管理 NSString内存管理 new、...

  • 第10章 内存管理和文件操作

    1 内存管理 1.1 内存管理基础 标准内存管理函数堆管理函数虚拟内存管理函数内存映射文件函数 GlobalMem...

  • 操作系统之内存管理

    内存管理 包括内存管理和虚拟内存管理 内存管理包括内存管理概念、交换与覆盖、连续分配管理方式和非连续分配管理方式(...

  • JavaScript —— 内存管理及垃圾回收

    目录 JavaScript内存管理内存为什么需要管理?内存管理概念JavaScript中的内存管理JavaScri...

  • OC - OC的内存管理机制

    导读 一、为什么要进行内存管理 二、内存管理机制 三、内存管理原则 四、MRC手动内存管理 五、ARC自动内存管理...

  • 3. 内存管理

    内存管理 内存管理包含: 物理内存管理; 虚拟内存管理; 两者的映射 除了内存管理模块, 其他都使用虚拟地址(包括...

  • Go语言——内存管理

    Go语言——内存管理 参考: 图解 TCMalloc Golang 内存管理 Go 内存管理 问题 内存碎片:避免...

  • jvm 基础第一节: jvm数据区

    程序内存管理分为手动内存管理和自动内存管理, 而java属于自动内存管理,因此jvm的职能之一就是程序内存管理 j...

  • 内存管理

    内存管理的重要性。 不进行内存管理和错误的内存管理会造成以下问题。 内存泄露 悬挂指针 OC内存模型 内存管理是通...

  • 11-AutoreleasePool实现原理上

    我们都知道iOS的内存管理分为手动内存管理(MRC)和自动内存管理(ARC),但是不管是手动内存管理还是自动内存管...

网友评论

      本文标题:内存管理

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