美文网首页
iOS内存管理

iOS内存管理

作者: 爱掏蜂窝的熊 | 来源:发表于2015-12-04 18:22 被阅读124次

    原文地址
    从开始的MRC(Manual Reference Counting)到后来ARC(Automatic Reference Counting),包括CoreFoundation的内存管理都遵守引用计数的基本原则。

    在MRC环境下,你使用alloc/new/copy/mutableCopy这些开头的方法创建了一个对象,调用retain方法返回对象,那么你就会拥有这个对象,新创建对象的引用计数器为1。当你不用的时候,你就需要手动的去release一次(引用计数器减1)

    在ARC环境下, 你使用alloc/new/copy/mutableCopy这些开头的方法创建了一个对象,xcode帮你在创建对象的时候添加内存管理的代码.

    举一个例子,假设有一个方法,[STObject newObject]

    - (instancetype)newObject {
        return [[[[self class] alloc] init] retain];
    }
    
    我们应该这么使用,如果我们最后不release,就会导致Object被泄漏。
    STObject *object = [STObject newObject];
    // do something
    [object release];
    

    那么就产生了以下几个问题:

    关键是看在那种环境(MRC or ARC)下创建对象#####
    • MRC下实现了一个newObject方法,该方法遵守约定的原则,返回值会retain 引用计数+1,然后在ARC下调用该方法创建对象 (xcode帮你添加内存管理的代码,只要MRC管理好对象的引用计数器就没问题)

    • MRC下实现了一个newObject方法,该方法 没有 遵守约定原则,返回autorelease的对象,然后在ARC下调用该方法创建对象 (MRC没有管理好对象的引用计数器,会引起野指针访问)

    • ARC下实现了一个newObject方法,然后在MRC下调用newObject方法创建对象,使用完成之后release (需要程序猿手动管理)

    • ARC下实现了一个newObject方法,然后在MRC下调用newObject方法创建对象,使用完成之后没有release (对象没有手动管理导致内存泄露)

    最终测试结果如下:

    场景1,3下运行正常
    场景2下会crash,访问坏内存( 野指针错误)
    场景4下产生内存泄露
    总结:
      不管创建对象的代码是写在MRC环境还是ARC环境,关键看调用创建对象的代码是在哪一个环境
      如果是在MRC环境创建对象,需要程序猿手动管理对象的引用计数器
      如果是在ARC环境创建对象,xcode帮你添加内存管理的代码,只要MRC管理好对象的引用计数器就没问题

    分析###

    为什么场景2会crash呢?这是由于ARC环境下,我们编译器如果看到你是以alloc/new/copy/mutableCopy等开头的方法创建了对象,则会在使用的最后插入一次release/autorelease操作,由于返回的是autorelease的对象,又被release了一次,所以导致野指针。

    场景4产生泄漏的原因也是一样,MRC下编译器发现该方法是new等开头的时候,方法结束的时候不会插入release语句,场景4使用的过程中,没有对newObject进行release,所以会产生泄漏。

    如果我们仅使用MRR或者ARC的话,这种问题一般不会出现。这种问题的出现一般是当ARC/MRR混编的时候,由于一些编写的不规范导致的,所以在写代码的过程中,遵守规范是很有必要的。

    MRC环境
    如果我们自己编写alloc/new/copy/mutableCopy开头的方法的时候,MRC下一定不要忘了返回retain的对象,同样当我们使用alloc/new/copy/mutableCopy的方法创建对象的时候,也不能忘了在用完之后release。

    相关文章

      网友评论

          本文标题:iOS内存管理

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