深入了解保留周期

时间:2013-11-10 16:41:49

标签: ios objective-c memory-management automatic-ref-counting retain-cycle

让我们说我们有三个对象:祖父母,父母和孩子。祖父母保留父母,父母保留孩子,孩子保留父母。祖父母释放父母。

在这种情况下会发生什么?

10 个答案:

答案 0 :(得分:69)

除非对父母或孩子有其他提及,否则他们都会成为孤儿。但是父母和孩子之间的保留周期阻止了被释放,并且它们变成了浪费的记忆。

孩子不应该留住父母。如果有的话,在子代中使用弱引用来维护对父代的引用。

答案 1 :(得分:26)

保留周期是条件当2个对象保持对彼此的引用并被保留时,它会创建一个保留周期,因为两个对象都试图相互保留,从而无法释放。

这里“祖父母”保留“父母”,“父母”保留“孩子”,而“孩子”保留“父母”。这里在父母和孩子之间建立保留周期。释放祖父母后,父母和子女都成为孤儿,但父母的保留计数不会为零,因为孩子会保留父母,因此会导致记忆管理问题。

有两种可能的解决方案:

1)使用指向父对象的弱指针,即子对象应该使用对父对象的弱引用,而不保留对父对象的弱引用。

2)使用“关闭”方法来打破保留周期。

http://www.cocoawithlove.com/2009/07/rules-to-avoid-retain-cycles.html

答案 2 :(得分:10)

在一个简单的例子中,考虑两个对象A和B,其中A创建并保留B.当创建A时,它创建B.当创建A的人最终释放它时,A' s保留计数降为零并且它被取消分配。如果A的dealloc方法调用B上的释放,则B&#39的保留计数也会降为零并且它也会被释放。 [这假设没有其他人保留A或B,因为我保持简单。]

但是如果B需要一个回到A的引用会发生什么呢?它会保留A?创建A的人可能会释放它。但由于B也保留了A,因此A的保留计数不会变为零。同样,由于A保留B,B的保留计数也不会归零。两者都不会被解除分配。即使B在其自己的dealloc中调用A的释放方法也无关紧要,因为该方法永远不会被调用。

此时你有内存泄漏,因为即使它们都存在,你也没有任何对A或B的引用。如果A或B正在执行任何处理器密集型操作,那么您可能还会将CPU时间泄漏到不需要的对象。

在你的情况下,A是父母,B是孩子,无论谁创建A是祖父母。

答案 3 :(得分:5)

保留周期是当对象A保留对象B时发生的循环,而对象B保留对象A.在这种情况下,如果任一对象被释放:

  • 对象A不会被释放,因为对象B持有对它的引用 它(保留计数> 0)。
  • 只要对象A有一个,对象B就不会被解除分配 引用它(保留计数> 0)。
  • 但是对象A永远不会被释放,因为对象B拥有一个 引用它(保留计数> 0)。
  • 直到无限

因此,这两个对象只会在程序的生命周期中闲逛,即使它们应该被释放,如果一切正常,也应该被释放。

答案 4 :(得分:4)

当祖父母释放父母时,父母仍然活着,因为孩子保留了父母。

答案 5 :(得分:1)

保留周期 2个对象相互保持并保留的条件,它会创建一个保留周期,因为这两个对象试图相互保留,使其无法释放。

示例:一个人住在一个​​部门,一个部门有一个人。

@class Department;

@interface Person:NSObject
@property (strong,nonatomic)Department * department;
@end

@implementation Person
-(void)dealloc{
    NSLog(@"dealloc person");
}

@end
@interface Department: NSObject
@property (strong,nonatomic)Person * person;
@end

@implementation Department
-(void)dealloc{
    NSLog(@"dealloc Department");
}
@end

然后这样称呼:

- (void)viewDidLoad {
    [super viewDidLoad];
    Person * person = [[Person alloc] init];
    Department * department = [[Department alloc] init];
    person.department = department;
    department.person = person;
}

您将看不到dealloc日志,这是保留圈。

答案 6 :(得分:1)

祖父母:约翰 父母:泰德 孩子:玛丽

这是我的示例,其中使用电话进行说明:

  • John打电话给Ted,想和Mary进行电话会议。

  • Ted对John说:“挂线,我要拨玛丽的电话”

  • Ted保留了John的电话,并呼叫了立即接听电话的Mary。

  • Mary对Ted说:“与John通话,直到我通过,我才会挂断电话”。

  • Ted很久没听到约翰的来信了,他打来电话去做别的事情。

  • John去和Ted和Mary合并通话,然后突然死了。

  • 玛丽被困在与约翰通电话的路上,但永远不会挂断,因为约翰不会回来!

答案 7 :(得分:0)

由于P对象的retainCount为1,因此当它释放时,其retainCount变为0,并调用其dealloc方法;这反过来调用C对象的释放,其保留计数也变为0;并调用它的dealloc方法。

对象P和C都将被释放。

当调用C对象的dealloc方法时,反过来调用GP对象的释放,但由于GP保留了2的保留计数,保留计数减少到1,并且它继续挂起周围。

答案 8 :(得分:0)

保留周期是一个死锁条件。 保留周期的实际示例: 如果两个对象彼此保持引用,而没有其他对象被释放。

示例:Rummy游戏

答案 9 :(得分:0)

当两个对象以这种方式互相引用时,它们将创建循环并被保留。这两个对象都试图保持彼此,在这种情况下,它们彼此紧密连接,无法释放称为保持周期