views:

496

answers:

3

I am trying to floss daily, get my exercise, and make sure I maintain a balance between my retains and releases.

Here is what has me puzzled. I have a ivar:

NSMutabledata *_alignmentData

and a synthesized property associated with it:

// .h file
@property (nonatomic, retain) NSMutableData *alignmentData;

// .m file
@synthesize alignmentData=_alignmentData;

I start to pull data from a server asynchronously:

self.connection = 
[[[NSURLConnection alloc] initWithRequest:theRequest delegate:self] autorelease];

And immediately after allocate a data buffer to be used subsequently in the asynchronous callbacks:

// This prints 0. Cool.
NSLog(@"BEFORE [_alignmentData retainCount] = %d", [_alignmentData retainCount]);

// Create a place to receive the data that will arrive asynchronously:
self.alignmentData = [NSMutableData data];

// This prints 2. Shouldn't this be 1 ?!?
NSLog(@" AFTER [_alignmentData retainCount] = %d", [_alignmentData retainCount]);

To complicate matters in the first asynchronous callback that fires after the above allocation of self.alignmentData, I inspect the retain count again:

- (void)connection:(NSURLConnection *)connection didReceiveResponse:(NSURLResponse *)response {

    // This prints 1. 
    NSLog(@"[_alignmentData retainCount] = %d", [_alignmentData retainCount]);
    [self.alignmentData setLength:0];

}

So, it appears that the retain count rises to 2 from 0 then drops to 1. Can someone explain to me how this is possible?

Note: I've been told not to use retain counts as a debugging aid but that is simply not practical in a non-garbage collected language such as Objective-C.

+3  A: 

Maybe because you're allocating the object with a count of +1 and autorelase, then it get set to a property, which calls a retain on it, so +2, and the original object is autoreleased, so it drops to +1.

Abizern
THis is the correct answer, [NSData data] returns an autoreleased object.
Elfred
It is correct, but less complete than the other two IMO.
Chuck
Elfed, aha! I was beginning to suspect this. Autorelease is the hidden reason for the momentary rise in retainCount. Thanks alot.
dugla
+5  A: 

From the Memory Management Programming Guide:

Retain Count

Typically there should be no reason to explicitly ask an object what its retain count is (see retainCount). The result is often misleading, as you may be unaware of what framework objects have retained an object in which you are interested. In debugging memory management issues, you should be concerned only with ensuring that your code adheres to the ownership rules.

I've never come across a situation where it's been useful to query an object's retainCount. If you follow proper memory management rules, you'll be fine.

As for your actual question, autoreleases don't happen immediately. They happen whenever the current autorelease pool happens to be popped. Since you're not explicitly managing any autorelease pools, then you have no control over when that autorelease happens. However, since you seem to be following correct memory management rules, you have nothing to worry about.

Dave DeLong
+5  A: 

It IS practical not to use retain counts as a debugging aid. In fact, it's experienced Objective-C coders who will tell you not to pay attention to retain counts. The people who worry about them in general are coders new to Objective-C, and they wind up being confused like you are.

You should not worry much about retain counts. The fact that something has more retains than you expect does not necessarily have anything to do with your code and does not necessarily indicate a bug, and the only way to determine which is the case is to use a proper debugging tool like you were advised to do in the first place.

In this particular case, 2 is the correct retain count for that object at that point in time because it was created with a retain count of 1, then retained by your setter method.

Chuck
Yes, yes, Chuck. I know I'm in the clear as far as balancing my retain/releases. I'm not leaking. Clang says I'm good to go. I will now officially swear off fretting over retain counts. Promise. Thanks for the - rather stern actually - admonishment.
dugla
Sorry if it sounded overly stern. That really wasn't my intention. I'd been going for clarity rather than watching my tone, because I've known people who have spent a lot of time fretting over retain counts and it really is just time wasted, so I want to help people realize that sooner rather than later.
Chuck