ARC与MRC

Posted Beche

tags:

篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了ARC与MRC相关的知识,希望对你有一定的参考价值。

一、通过引用计数管理内存 

1、引用计数。通过引用计数管理内存。对象被创建出来时,引用计数至少为1,通过retain使引用计数递增,通过release、autorelease使引用计数递减,引用计数为0时,对象所在的内存为可重用,所有指向该对象的引用都无效。

2、dangling pointer。指向对象的引用计数为0的引用。使用dangling pointer不一定使程序崩溃,崩溃是否,看对象内存是否被覆写。

3、引用树。ios应用程序中的root object为UIApplication对象。

4、属性存取。strong relationship修饰的属性,在setValue时,先保留新值,再释放旧值。这个顺序不能颠倒,一旦颠倒,假如新值和旧值为同一个对象,释放后有可能对象已被回收,再保留就会出现问题。

5、autorease。在return方法内部创建的对象时,由于不能在方法内部释放对象(对象引用计数值有可能为0,对象就被回收),就得通过autoreleasepool使引用计数值在下一次event loop时递减。通过类工厂方法创建的对象放置在autoreleasepool中。

6、retain cycle。导致内存泄漏,解决问题有两种办法,一是weak reference,一是代码控制其中的某个对象不再保留另外一个对象。

7、Clang编译器中的静态分析器(static analyzer)。可以查明内存管理问题,也可以根据需要,预先加入保留与释放操作。

注意:retaincount方法获取引用计数值是不太有用的。对引用计数器做递增或递减操作时,只能说做了递增或递减操作,而绝不能说保留计数一定是某个值。

 

二、ARC自动引用计数(编译器与运行期组件共同管理内存)

1、实现思路是static analyzer。

2、代码中存在retain、release、autorelease、dealloc时,编译器无法通过。在调用这些方法时,不通过oc的消息派发机制,直接调用底层的c语言函数。

3、ARC命名规则。以alloc、new、copy、mutableCopy开头的方法名,对象归方法调用者持有。详解如下:

/* newPerson方法中,方法调用者持有返回对象。因此在方法内部,除了allo使引用计数+1外,没有其余的保留与释放操作,最后在调用方法后,对象需要增加一次释放操作。*/
+ (Person *)newPerson{
    Person *person = [[person alloc] init];
    return person;
}
/*createPerson方法中,方法调用者不持有返回对象,因此在return操作时,ARC会增加 [person autorelease] 方法。最后计数器平衡。*/
+ (Person *)createPerson{
    Person *person = [[person alloc] init];
    return person;
}

 

4、ARC有时会成对移除保留、释放操作。

5、ARC包含运行期组件。

如果方法名没遵守命名规则,但返回值赋值给强引用修饰的变量,无疑需要增加retain操作。考虑到backward compatibility性能,createPerson方法的return语句不用[person autorelease]替换,而改用objc_autoreleaseReturnValue(person)替换。

objc_autoreleaseReturnValue方法底层实现。此方法会检视方法返回后,是否要执行retain操作。如果要执行retain操作,则会设置全局数据结构中的一个标志位,并且方法中的return对象不会自动释放。而且在执行retain操作时,[person retain]也会用 objc_retainAutoreleaseReturnValue(person)方法代替,检查到标志位已经置位,则不执行保留操作。

设置标志位和检查标志位是否已置位(编译器执行),比保留和释放快。

 

6、ARC中局部变量与实例变量修饰符。

strong:保留此值,默认语义;

weak:不保留此值,并且值被回收后,指向nil;

 

7、ARC中的dealloc方法。

1)、dealloc方法不允许发送release消息,不允许给父类发送dealloc消息。ARC借助Objective-C++的一项特性生成清理例程(Objective-C++特性:回收Objective-C++对象时,待回收对象会调用所有C++对象的析构函数,编译器发现对象中存在C++对象,就会生成.cxx_destruct方法)在.cxx_destruct方法中自动生成代码,包括给父类发送dealloc消息。单例对象不会自动析构

2)、必要时添加CFRealease(Core Foundation对象)、free(通过malloc()分配的内存)方法、注销通知等等。ARC中的dealloc方法仅释放引用并解除监听

3)、释放引用不包括file descriptor、socket、大块内存等,通常创建另一个方法来释放这些引用,且另一个方法的调用必须在dealloc执行之前。不在dealloc中释放这些资源的原因:一是通过dealloc释放,资源保留时间过长;二是dealloc方法不一定执行。

4)、执行异步任务的方法不应在dealloc中调用,只能在正常状态下执行的方法也不应在dealloc中调用。

 

8、ARC中可能出现内存泄露的地方:

1)、出现相互强引用,导致双方都无法释放(retain cycle);

2)、c代码的对象,是不会自己释放的,比如cg(CoreGraphics.frameworks)开头的对象。

3)、GCD对象。

以上是关于ARC与MRC的主要内容,如果未能解决你的问题,请参考以下文章

OC 内存管理:MRC与ARC

iOS之深入解析内存管理MRC与ARC机制

ARC与MRC

iOS 中 ARC 项目 兼容 MRC

MRC和ARC混编

ARC和MRC混合使用