2
votes

Possible Duplicate:
Incorrect decrement of the reference count of an object that is not owned at this point by the caller
Why shouldn't I use the getter to release a property in objective-c?

So, I get that using [self.myProperty release] is discouraged (Apple itself recommends not to). Although it appears to me that it COULD lead to problems in some cases, not all cases. Is this correct? More importantly: I don't get why using a syntax like [self.myProperty release] in my -dealloc method(s) will cause the static analyzer to show an "incorrect decrement" error. Despite any other reason discouraging such a syntax, my class still owns its properties (which I have declared with "nonatomic,retain") so why the warning?

I've been reading several posts on this but it seems I can't really wrap my mind around it. Some of them go into details about the possible side effects of using such a syntax, but what I really want to know is the reason behind the "incorrect decrement" error.

Any help would greatly be appreciated.

3

3 Answers

4
votes

Cocoa memory management has a concept of "ownership" which is expressed most succinctly in the rule: If you call new or alloc, or send retain or copy to an object, you own the result, and are responsible for sending release when you're done with it. Otherwise, you do not own it, and you must not send release.

Instance variables, basically by definition, contain objects that the instance owns. You need the objects to be valid for the life of the instance, so you create them with an ownership-granting method in init:

// myDinkus and creationDate are ivars of whatever class this is.
// They are assigned to with owned references.
myDinkus = [[Dinkus alloc] init];    // ownership due to alloc
creationDate = [[NSDate date] retain];    // ownership due to retain

These now need to be sent release when the instance is done with them; generally speaking, this will be in dealloc.

Getter methods don't return owning references. This is the way it should be; when your code, e.g., asks a label for its font color, it doesn't need that color object to stick around. Or if it does, it must explicitly take ownership by sending retain. Giving it ownership by default would create headaches at best and possibly leaks.

That established, [self.myProperty release] causes the static analyzer to complain because it's a violation of the ownership concept. The object returned from [self myProperty] isn't owned by the caller. The fact that it just so happens to be the same object as an ivar that is owned by the caller is irrelevant. (In fact, it might not be the same; the getter might return a copy of the object it represents, for example. It might construct an entirely new value based on a group of ivars. It's even possible for there to be no ivar that corresponds to a getter.)

Since objects which are not owned must not be sent release, doing so to the result of a getter is incorrect.

There are other, practical, reasons not to do this (covered quite well, especially by Justin's answer in the question proposed as dupe), but that's the reason the analyzer is complaining.

1
votes

Fundamentally, you're sending a release message to an object that you haven't sent a retain to (at least not explicitly). The static analyzer will expect to see balanced retain/releases.

1
votes

When you declare your property as nonatomic,retain you are handing responsibility for releasing the value to the property's setter.

If you do a [self.myProperty release] then your property still contains its old value and any subsequent setting of that property will do a release on that old value - but you've already released it, so now it is over-released... Hence the warning.

To release the value you should use self.myProperty = nil - the setter will release the old value and assign nil to the property.