1

Now I have a ClassA : NSObject, and then in the viewcontroller viewDidLoad, look at the under code:

- (void)viewDidLoad {
    ClassA *a = [[ClassA alloc] init];
    NSLog(@"a retainCount = %d", [a retainCount]);
    ClassA *b = a;
    NSLog(@"a retainCount = %d b retainCount= %d ", [a retainCount],[b retainCount]);
    [a release];
    NSLog(@"a retainCount = %d b retainCount= %d", [a retainCount],[b retainCount]);
    [super viewDidLoad];
}

The console output looks like:

2012-11-02 14:43:35.437 RetainCountTest[1043:207] a retainCount = 1
2012-11-02 14:43:35.439 RetainCountTest[1043:207] a retainCount = 1 b retainCount= 1  
2012-11-02 14:43:35.439 RetainCountTest[1043:207] a retainCount = 1 b retainCount= 1

I don't understand that when I call [a release], why the [a retainCount]== 1

mttrb
  • 8,297
  • 3
  • 35
  • 57
Maggie
  • 33
  • 1
  • 4
  • 1
    An interviewer asked about retainCount? – bbum Nov 02 '12 at 14:45
  • @bbum Maybe it was a trick question and “you should never send `retainCount`, especially to a dead object” was the correct answer. – Peter Hosey Nov 02 '12 at 22:33
  • That is seriously what I'm hoping. If the interviewer were any good, a follow up on concurrency or autorelease would be telling. (And I wouldn't necessarily ding someone who thought `retainCount` was useful -- always interesting to see how willing a candidate is to change positions when confronted with information that invalidates their current position). – bbum Nov 02 '12 at 23:20

3 Answers3

4

That's because "retainCount is useless".

To add some context: You should expect undefined behavior when messaging an object which is 'dead'.

justin
  • 104,054
  • 14
  • 179
  • 226
  • I generally don't like such short answers, but the linked article explains it all very well. – justin Nov 02 '12 at 07:03
  • Thank you very much,justin, today, an interviewer give me a test, and I answered this should became 0 when you use [a release], now I test it in Xcode, it still output 1, so I am confused. Can I ask: where the a retainCount became 0? – Maggie Nov 02 '12 at 07:07
  • 1
    @Maggie From point #5 in the linked article: "The retainCount method can never return 0." specifically, you should expect no more than undefined behavior in this case. if you want to track reference count operations, Instruments will record them for you. – justin Nov 02 '12 at 07:20
1

You should never pay attention to retainCount's. They are at best confusing, and at worst misleading. One should just make sure that they follow memory management rules of retain/release correctly, and forget about retainCounts.

From documentation..

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.

EDIT : Suggested Reading

When to use -retainCount?

EDIT : After seeing OP's comment

From Cocoa Core Memory Management rules

When you create or copy an object, its retain count is 1. Thereafter other objects may express an ownership interest in your object, which increments its retain count. The owners of an object may also relinquish their ownership interest in it, which decrements the retain count. When the retain count becomes zero, the object is deallocated (destroyed).

If one read this, he/she might think, Oh retainCount is godsent, and I can see the complete alloc/retain/release cycle of an object just using an NSLog statement. But it doesn't actually works that way. You cannot say, you have sole ownership of object you create. That object might be retained by any other framework object. And by releasing you are just relinquishing your ownership. The object will get released only after all other objects remove their reference.

I don't know why it remains in public API.

Community
  • 1
  • 1
Krishnabhadra
  • 34,169
  • 30
  • 118
  • 167
  • Thank you very much,krishnabhadra, today, an interviewer give me a test, and I answered this should became 0 when you use [a release], now I test it in Xcode, it still output 1, so I am confused. – Maggie Nov 02 '12 at 07:05
  • Thank you again, @Krishnabhadra, you are right,I should follow the rules of memory managerment. – Maggie Nov 02 '12 at 07:24
  • FWIW, it is illegal to send a `retainCount` message, or have an `@selector(retainCount)` literal, in ARC. – Peter Hosey Nov 02 '12 at 18:56
1

When you call [a release], you're not holding on to a anymore, so a might get deallocated. It's probably the case here since its ownership is mot shared.

Any further message to a has an undefined return value: another object might have reused a's memory slot.

So the return value you print is essentially random. It might have crashed your app or printed 1000...

Thomas Deniau
  • 2,488
  • 1
  • 15
  • 15