Understanding retain cycle in depth
Asked Answered
D

10

60

Lets say we have three objects: a grandparent, parent and child. The grandparent retains the parent, the parent retains the child and the child retains the parent. The grandparent releases the parent.

What will happen in this case ?

Deforest answered 10/11, 2013 at 16:41 Comment(0)
A
77

Unless there is some other reference to the parent or child, they both become orphaned. But the retain cycle between the parent and child prevent either from being released and they become wasted memory.

A child should never retain a parent. If anything, use a weak reference in the child to maintain a reference to the parent.

Arkwright answered 10/11, 2013 at 16:44 Comment(3)
Just wanted to add that in some rare cases it can be useful to have a child retain a parent, you just need to add a method that will break the loop at some point (and guarantee that it will be called when the objects need to be cleaned up).Transalpine
@Transalpine When would a child need to retain a parent? It's fine to have a weak reference to a parent, but why a strong reference?Arkwright
@Arkwright perhaps something where you set an animation or other timer-based activity off running by itself, and you no longer own it. You would want it to stick around as long as it needs to, and clean up after itself.Perimeter
A
29

Retain Cycle is the condition When 2 objects keep a reference to each other and are retained, it creates a retain cycle since both objects try to retain each other, making it impossible to release.

Here The "Grandparent" retains the "parent" and "parent" retains the "child" where as "child" retains the "parent".. Here a retain cycle is established between parent and child. After releasing the Grandparent both the parent and child become orphaned but the retain count of parent will not be zero as it is being retained by the child and hence causes a memory management issue.

There are two possible solutions:

1) Use weak pointer to parent , i.e a child should be using weak reference to parent, which is not retained.

2) Use "close" methods to break retain cycles.

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

Allodium answered 10/11, 2013 at 17:20 Comment(0)
O
11

In a simple case, consider two objects A and B where A creates and retains B. When A is created, it creates B. When whoever created A finally releases it, A's retain count drops to zero and it gets deallocated. If A's dealloc method calls release on B, B's retain count also drops to zero and it also gets deallocated. [This assumes that nobody else has retained A or B, because I'm keeping things simple.]

But what happens if B needs a reference back to A, and it retains A? Whoever created A might release it. But since B has also retained A, A's retain count won't go to zero. Likewise, since A retains B, B's retain count also won't go to zero. Neither will be deallocated. Even if B calls A's release method in its own dealloc it doesn't matter, because that method is never going to be called.

At this point you have a memory leak, because you don't have any reference to A or B even though they both still exist. If A or B is doing anything processor intensive then you might also be leaking CPU time to unwanted objects.

In your case A is parent and B is child and whosoever created A is grandparent.

Ochone answered 10/8, 2015 at 6:40 Comment(0)
N
5

A retain cycle is a loop that happens when Object A retains Object B, and Object B retains Object A. In that situation, if either object is released:

  • Object A won't be deallocated because Object B holds a reference to it (retain count > 0).
  • Object B won't ever be deallocated as long as Object A has a reference to it (retain count > 0).
  • But Object A will never be deallocated because Object B holds a reference to it (retain count > 0).
  • till infinity

Thus, those two objects will just hang around in memory for the life of the program even though they should, if everything were working properly, be deallocated.

Novelette answered 26/6, 2016 at 8:54 Comment(1)
@Balasubramanian we keeping weak reference in either object, depends which object owns other object, Owner should keep strong reference and other one weak.Novelette
J
4

When grandparent release the parent the parent is still alive as the child retain the parent.

Jahn answered 10/11, 2013 at 16:55 Comment(0)
U
2

Grandparent: John Parent: Ted Child: Mary

Here is my example using a telephone call for illustration:

  • John calls Ted and wants to do a conference call with Mary.

  • Ted Says to John: "Hang on the line, and I will dial in Mary"

  • Ted leaves John on hold and calls Mary who promptly answers the phone.

  • Mary says to Ted: "Merge my call in with John and I WILL NOT hang up until I'm through"

  • Ted, having not heard back from John in a while, leaves the call to do something else.

  • John goes to merge the calls with Ted and Mary and then suddenly dies.

  • Mary is stuck on the line to John but will never hang up cause John ain't coming back!

Underexpose answered 22/1, 2019 at 16:38 Comment(0)
G
1

Retain Cycle is the condition when 2 objects keep a reference to each other and are retained, it creates a retain cycle since both objects try to retain each other, making it impossible to release.


Example: A person lives in a department, a department has one person.

@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

Then call it like this:

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

You will not see dealloc log, this is the retain circle.

Grattan answered 23/10, 2017 at 13:43 Comment(0)
V
0

Since the P object has retainCount of 1, when it is released, its retainCount goes to 0, and its dealloc method is called; This in turn calls release on C object, whose retain count also goes to 0; and its dealloc method is called.

Both objects P and C will get freed.

When C object's dealloc method is called, in turn GP object's release is called, but since GP holds a retain count of 2, the retain count is decremented to 1, and it continues to hang around.

Valente answered 18/4, 2014 at 18:7 Comment(2)
P has retainCount of 2 before being released by GP (it is retained by GP and C).Transalpine
You are right. Read the original question little differently and incorrectly-:). I read the question to be gp->p->c->gp retain cycle instead of gp->p->c->p cycle.Valente
T
0

Retain cycle is a deadlock condition. Real Life Example of Retain Cycle: If two object hold a reference each other and no other object is released.

Example: Rummy Game

Torso answered 19/2, 2019 at 16:41 Comment(0)
C
0

When two objects keep references of each other in such a way the objects create cycle and are retained. Both objects try to retain each other, in this case they are strongly connected with each other and impossible to release is called retain cycle

Cleareyed answered 4/3, 2020 at 6:20 Comment(0)

© 2022 - 2024 — McMap. All rights reserved.