The dealloc method is not called when setting the object to nil

I have a question.

First I created an object that extends NSObject, I provided overrides for the description and dealloc methods. Here is my Employee.m file:

@implementation Employee ..... -(NSString *)description { return [NSString stringWithFormat:@"Employ ID: %d has $%d value of assets", [self employeeID], [self valueOfAssets]]; } -(void)dealloc { NSLog(@"deallocating.. %@", self); [super dealloc]; } 

In my main.m, I first created an NSMutableArray to store a list of Employee objects:

 NSMutableArray *employees = [[NSMutableArray alloc] init]; for (int i =0; i< 10; i++) { // Create an instance of Employee Employee *person = [[Employee alloc] init]; // Give the instance varaible interesting values [person setEmployeeID:i]; [employees addObject: person]; } 

and in the end I installed employees on nil

 employees = nil; 

I expected the dealloc method for each Employee object to be called, and I will see several logs, for example:

 deallocating.. Employ ID 0 has value..... deallocating.. Employ ID 2 has value..... .... 

However, I did not see any logs, and if I set a breakpoint in the dealloc method, the breakpoint would never hit.

Any thoughts?

+3
source share
3 answers

A few observations:

  • person = nil does not free an object in code other than ARC. It will be in ARC code (at least if it is strong).

  • In ARC, local objects will be automatically released automatically when they go out of scope. In non-ARC, objects falling out of scope will not be released to you (and if you have no other references to these objects elsewhere, you will receive a leak).

  • Adding an element to a variable array will increase the number of element holdings, so even if you include release in your code without ARC, the object will not be released until the save count drops to zero (this is done not only by releasing person objects after adding them to the array , but also removing them from the array.

So, given that this is non-ARC code, it could be something like:

 - (void)testInNonArcCode { NSMutableArray *employees = [[NSMutableArray alloc] init]; // employees retain count = +1 for (int i =0; i< 10; i++) { //create an instance of Employee Employee *person = [[Employee alloc] init]; // person retain count = +1 //Give the instance varaible interesting values [person setEmployeeID:i]; [employees addObject: person]; // person retain count = +2 [person release]; // person retain count = +1 (YOU REALLY WANT TO DO THIS OR ELSE OR NON-ARC PROGRAM WILL LEAK) // person = nil; // this does nothing, except clears the local var that limited to the for loop scope ... it does nothing to reduce the retain count or improve memory management in non-ARC code, thus I have commented it out } // do whatever you want [employees removeAllObjects]; // this will remove all of the person objects and they will have their respective retain counts reduced to 0, and therefore the Employee objects will be released [employees release]; // employees array own retain count reduced to zero (and will now be dealloced, itself) } 

In the ARC code:

 - (void)testInArcCode { NSMutableArray *employees = [[NSMutableArray alloc] init]; // employees retain count = +1 for (int i =0; i< 10; i++) { //create an instance of Employee Employee *person = [[Employee alloc] init]; // person retain count = +1 //Give the instance varaible interesting values [person setEmployeeID:i]; [employees addObject: person]; // person retain count = +2 // person = nil; // this would reduce person retain count to +1 (but unnecessary in ARC because when person falls out of scope, it will have it retain count automatically reduced) } // do whatever you want [employees removeAllObjects]; // this will remove all of the person objects and they will have their respective retain counts reduced to 0, and therefore will be released // [employees release]; // not permitted in ARC // employees = nil; // this would effectively release employees, but again, not needed, because when it falls out of scope, it will be released anyway } 
+8
source

The correct way to free objects is to do

 [employees release]; 

Setting to nil will not free up memory.

+3
source

Since you are allowed to call [super dealloc] , I can assume that you are not using Automatic Link Counting . This means that you need to explicitly match each alloc you write with the release balancing call. For you, when you create the nil array, you essentially leaked all the memory for the employees. You need to iterate over the array again to free them all, or even better since you study ... Start as soon as possible by writing ARC code.

Perhaps it is important to note that ARC was created specifically for this kind of situation; it makes sense to our brain, and now it can be a reality if you use the latest tools.

+2
source

All Articles