Re: How is this an "incorrect decrement of a reference count"?
Re: How is this an "incorrect decrement of a reference count"?
- Subject: Re: How is this an "incorrect decrement of a reference count"?
- From: David Duncan <email@hidden>
- Date: Mon, 19 Mar 2012 15:42:35 -0700
On Mar 19, 2012, at 5:18 AM, G S wrote:
> self.imagePicker = [[UIImagePickerController alloc] init];
>
> [self.imagePicker release];
>
> I do this in many places, but in a few of them the analyzer says:
>
> *Property returns an Objective-C object with a +0 retain count*
> *Incorrect decrement of the reference count of an object that is not owned
> at this point by the caller*
>
> Is this just a bug in the analyzer? I can find no difference between the
> times it makes this complaint and the many more times that it doesn't.
This is always an anti-pattern, even if the analyzer doesn't always point it out (and I'm not certain why it wouldn't in some places…).
The reason why its an anti-pattern is because an accessor is not like an ivar. [[self imagePicker] release] means something very very different from [_imagePicker release]. In the former case you are releasing the result of something you do not own (the result of an accessor like -imagePicker is an unowned object, even if it is from an accessor in your own class) and as such releasing it is invalid.
Now you might think you could do something like this instead:
self.foo = [[NSFoo alloc] init];
[_foo release];
But thats also an anti-pattern, but for a more subtle reason, and that is because (especially if your synthesizing it) your code shouldn't rely on the implementation details of -setFoo: beyond what the property declaration proscribes. For example, if the new incoming value is the same as the old value, you can't be guaranteed that the retain count has actually changed, thus the -release would be invalid.
But even more so, this gets problematic if you change your property to be a 'copy' property – either of the previous versions will fail completely with a -copy property where the copy actually takes place, as the new object in _foo will only have a single owner – your instance – and you will then release it behind the back of the accessor. Your next access of that accessor will then cause your application to reference an invalid object.
Basically your safe options are to either:
1) Use a temporary that you release:
id foo = [[NSFoo alloc] init];
self.foo = foo;
[foo release];
2) Use -autorelease:
self.foo = [[[NSFoo alloc] init] autorelease];
3) Use ARC which will manage this for you.
I would highly recommend #3 overall.
--
David Duncan
_______________________________________________
Cocoa-dev mailing list (email@hidden)
Please do not post admin requests or moderator comments to the list.
Contact the moderators at cocoa-dev-admins(at)lists.apple.com
Help/Unsubscribe/Update your Subscription:
This email sent to email@hidden