【问题标题】:Retain cycle with parent-child construction带父子构造的retain循环
【发布时间】:2015-08-12 02:42:24
【问题描述】:

这是每个人都熟悉的非常常见的问题,但我仍然没有完全理解它。

如果对象A拥有对象B(具有强属性),而对象B具有对象A的强属性,则存在retain循环,无法释放对象,存在内存泄漏。

但是,如果对象 A 将指向对象 C 而不是对象 B,那么内存中的另一个地址呢?

据我所知,强属性的作用如下:

- (void)setObject:(id)newObject{
if (_newObject == newObject){
return; //
}

NSObject *oldObject = _newObject;
_newObject = [newObject retain];
[oldObject release];
}

那么,如果我们指向对象 C,那么对象 B 的内存不是会被释放吗?如果两个对象(A 和 B)都改为设置 nil 对象怎么办?是否还会存在内存泄漏的保留周期?旧值“浮动”在内存中的某处?

我知道,这已经讨论过很多次了,但我仍然无法在脑海中获得“全貌”。对此问题的任何澄清,我将不胜感激。

【问题讨论】:

  • 分配工具具有帮助检测周期的工具。我建议您探索上述工具。如果您想编写示例代码来玩,请创建自己的 NSObject 子类,这样您就不会遇到静态实例(如 @"foo")或标记指针。

标签: ios objective-c memory-management memory-leaks retaincount


【解决方案1】:

如果问题是“您能否通过重新分配其中一个属性来打破保留周期?”,答案是肯定的。如果您将 nil 分配给属性,这同样适用。

【讨论】:

  • 如果只重新分配一个属性 - 设置为零,就足以摆脱保留循环?
  • 是的。因为当两者相互引用时,循环就存在。因此,如果 A -> B 但 B -> NIL,则没有循环。但这都是学术性的,你应该使用强 A-> B 和弱 B->A (或分配,但通常弱是合适的)。
【解决方案2】:

您要查找的词是“保留周期”。

最简单的保留循环是对自身具有强引用的对象。非常罕见,因为它毫无意义。

最常见的情况是A对B有强引用,B对A有强引用。A->B->A。你看到循环了吗?

循环可以是任意长度 A->B->C->D->E->F->G->...->A。这是一个保留周期,因此不会释放任何内容。如果您只有 A->B->C->D->...->Z 而没有引用回序列中的另一个对象,那么就没有循环。没有循环,没有问题。

【讨论】:

  • 那么,如果我们有循环A>B>A,然后我们做A>C和B>D,具有相同的强引用,不会有内存泄漏,因此保留循环?跨度>
  • 对自身有强引用的对象在今天并不罕见,顺便说一句,因为 Swift 中的对象可以有闭包作为它们的属性,一旦你访问任何对象,它就会捕获对 self 的强引用闭包内self 的属性或方法。 Obj-C 块也可能导致 self 的保留周期,如下所述:stackoverflow.com/questions/4352561/…
  • @EvgeniyKleban 这个答案和 JeremyP 的答案都是正确的。
猜你喜欢
  • 1970-01-01
  • 2015-01-21
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2020-11-24
  • 2018-12-06
  • 1970-01-01
相关资源
最近更新 更多