0

I am playing with objective-c and did sample test. In non-arc environment I have the following code:

NSNumber * one;
NSLog(@"At first one retain count is: %d",[one retainCount]);

one = [[NSNumber alloc]initWithInt:5];
NSNumber * two = [[NSNumber alloc]initWithInt:1];
NSNumber * three =[[NSNumber alloc]initWithInt:2];

NSLog(@"After initializing %d",[one retainCount]);

NSMutableArray * array = [NSMutableArray arrayWithObjects:one,two,three, nil];
NSLog(@"After adding to array it is: %d",[one retainCount]);

NSString * a = [array objectAtIndex:0];
NSLog(@"Assigning to variable a: %d",[one retainCount]);
NSLog(@" %@ ",a);
[one release];
[array removeObjectAtIndex:0];
NSLog(@"after releasing and removing from array %d",[one retainCount]);
NSLog(@" %@ ",a);

It seems like the I wouldn't be able to use nslog the variable a but I can do it. I am getting the following output;

2013-03-07 17:57:09.706 Interview[33491:11303] At first one retain count is: 3
2013-03-07 17:57:09.707 Interview[33491:11303] After initializing 2
2013-03-07 17:57:09.707 Interview[33491:11303] After adding to array it is: 3
2013-03-07 17:57:09.707 Interview[33491:11303] Assigning to variable a: 3
2013-03-07 17:57:09.707 Interview[33491:11303] 5
2013-03-07 17:57:09.707 Interview[33491:11303] after releasing and removing from array 1
2013-03-07 17:57:09.708 Interview[33491:11303] 5

How it's possible that I can still use the variable a even if I it supposed be deallacated?

rmaddy
  • 314,917
  • 42
  • 532
  • 579
Janusz Chudzynski
  • 2,700
  • 3
  • 33
  • 46
  • 1
    Don't ever call `retainCount`. It's never the right thing to do, and you'll probably just end up confusing yourself. See: http://stackoverflow.com/a/2640606/116908 – Carl Norum Mar 08 '13 at 00:02

3 Answers3

3

You'll get told many times you should not use retainCount, but your question is:

How it's possible that I can still use the variable a even if I it supposed be deallacated?

When an object is deallocated that simply means that the memory that was used for it is added to the pool of available memory. The memory previously in use is not completely overwritten to remove all traces of what was stored in it.

Furthermore when you invoke [one release] this only indicates you no longer have an interest in the object referenced by the value stored in one (and as a result that object's memory may be returned to the free pool) it does not alter the value stored in one itself. So after the call one still contains the reference to where the object was, or still is...

If you wish to make sure you don't use an out-of-date reference you can use code like:

 [one release]; one = nil;

Finally you report that before you even allocate your object your first NSLog outputs:

2013-03-07 17:57:09.706 Interview[33491:11303] At first one retain count is: 3

How can you have a retain count of 3 when you've never even allocated an object? The answer is you are lucky your code didn't blow up; when a local variable, which your one appears to be, is created it starts with garbage contents - calling a method using that garbage as an object reference is unwise. Remember Objective-C is not a "safe" language and will not protect you from such errors. Note that instance and global variables are initialised to 0/nil, and invoking methods on nil is supported in Objective-C - you just get 0 back.

CRD
  • 52,522
  • 5
  • 70
  • 86
2

Because you can never be fully sure that your object hasn't been retained elsewhere in the framework. Be sure you obey the memory management policy, and let the framework worry about its obligations.

Additionally, don't use retainCount. Apple tells you explicitly not to use it, and it isn't guaranteed to tell the truth.

Directly from the documentation: Do not use this method.

Special Considerations

This method is of no value in debugging memory management issues. Because any number of framework objects may have retained an object in order to hold references to it, while at the same time autorelease pools may be holding any number of deferred releases on an object, it is very unlikely that you can get useful information from this method.

To understand the fundamental rules of memory management that you must abide by, read “Memory Management Policy”. To diagnose memory management problems, use a suitable tool:

  • The Clang Static analyzer can typically find memory management problems even before you run your program.
  • The Object Alloc instrument in the Instruments application (see Instruments User Guide) can track object allocation and destruction.
Michael Robinson
  • 29,278
  • 12
  • 104
  • 130
  • thank you I realize I can't trust retain count. How would you explain that I can still print the content of variable a that what I believe should be deallocated? – Janusz Chudzynski Mar 08 '13 at 00:16
  • @JanuszChudzynski I've just updated my answer - basically because the framework has likely `retain`ed it elsewhere. See my updated answer for more details. – Michael Robinson Mar 08 '13 at 00:17
  • And which Framework did it? I had this question on interview and I said that in such scenario (my code above) in the best case nothing will happen and in the worst my app will crash. So if I understand it correctly if it would work like it's described in Apple's documents it should crash and give me some kind of BAD Access error. Am I correct? – Janusz Chudzynski Mar 08 '13 at 00:24
  • As far as you're concerned, you've fulfilled your obligations as far as `retain`/`release` go. So on your final log of `one`, yes it should crash. But sometimes it won't. Thus the importance of sticking to the rules - if you want to use an object, don't release it. When you're done, release it. After you release it, don't try to use it again - as far as you're concerned it's gone (even if it's sometimes not). – Michael Robinson Mar 08 '13 at 00:34
  • I have a last question @Micheal Robinson. Would it be different in ARC conditions? (of course I wouldn't send release message to variable one). – Janusz Chudzynski Mar 08 '13 at 00:38
2

Look here, this explains everything more clearly:

http://www.whentouseretaincount.com

Kaan Dedeoglu
  • 14,765
  • 5
  • 40
  • 41