如何发生过度释放或过度保留?

时间:2015-09-07 01:50:10

标签: objective-c automatic-ref-counting release retain

不确定这个问题是否过于宽泛,在这种情况下,你可以用更为一般的先例解释并提供一些例子。

3 个答案:

答案 0 :(得分:2)

根据您的标签判断,我将专门回答ARC。

当部分代码不恰当地创建引用时,对象通常会被过度保留

例如,过度保留的常见方式是两个对象之间是否具有强引用。强引用可防止对象被释放 - 在两个对象以这种方式相互引用的情况下,则创建一个循环,这意味着在另一个对象出现之前都不会被释放。

另一个例子是使用块作为变量。假设一个对象有一个实例块变量/属性,其中包括:

self.blockProperty = ^{
    self.property = value;
};

这会在块内为对象本身创建一个强引用。这里正确的做法是创建一个对self的弱引用并在块中使用它,但这种细微之处常常容易被忽视。

另一方面,当相反的情况发生时,对象通常是过度释放,即当代码具有对实际依赖的对象的弱引用时。这可能意味着在仍然需要时对象被释放。或者,该对象可能无意中被设置为nil,或者可能从未首先启动过。

这些问题(根据我的经验)在使用ARC时不那么常见,但这并不意味着你可以忘记它们。良好的分析工具的使用有助于挑选前者,并且您通常会知道后者是什么问题,因为您将看到EXC_BAD_ACCESS或类似的,这总是很有趣的调试。但是,由于弱引用在其目标被释放时设置为nil,因此不会总是如此,因此当您尝试向其发送消息时,您可能无法获取错误。< / p>

答案 1 :(得分:1)

过度发布当对象收到的消息多于release消息时发生<{1}}消息,也就是说,当最后retain消息发送到release消息时,它已被解除分配它。结果通常是崩溃或未定义的行为。

Overretain 表示您的代码中有一个retain从未与release(忘记release某处)配对,该对象从未被释放。创建了自动释放池和autorelease消息以防止 overretain 。结果通常是应用程序需要太多内存,但用户不会注意到错误是否多次重复。

当然,这只能在手动参考计数(MRC)下进行,因为在自动参考计数(ARC)下,您永远不会手动发送retainrelease

在对象使用手动引用计数(例如Core Foundation对象)时,有一些特定情况,您必须使用__bridge强制转换才能在ARC下使用它们。如果您错误地使用桥接模型,可能会出现类似的问题。我不确定这个名称是overrelease还是overretain

顺便说一下,不要把保留周期混淆得过多。这是一个不同的错误,在MRC和ARC下有不同的解决方案。

答案 2 :(得分:-1)

在ARC环境下,仅在__bridge_transfer__bridge_retained强制转换时发生过度释放和过度保留(Core Foundation提供与CFBridgingReleaseCFBridgingRetain相同的功能)。

过度释放:

NSObject *obj = (__bridge_transfer NSObject*)(__bridge void*)[[NSObject alloc] init];

过保留:

NSObject* obj = (__bridge NSObject*)(__bridge_retained void*)[[NSObject alloc] init];