In a book, the following is said:
So how do you know when an object is owned, and by whom? Consider the following example:
NSString *str = [[NSString alloc] initWithString:@”Hello”]; NSString *str2 = str;
In this example, you use the
alloc
keyword forstr
, so you ownstr
. Therefore, you need to release it when it’s no longer needed. However,str2
is simply pointing tostr
, so you do not ownstr2
, meaning you need not releasestr2
when you are done using it.
I thought ownership is by object, not variable or pointer... so we can't say we "own str
" or "own str2
"... we own an object, which is pointed to by either str
or str2
, and if we use [str release]
or [str2 release]
, it is all the same.
The other description is:
For example, consider the example used in the previous section:
NSString *str = [[NSString alloc] initWithString:@”Hello”]; NSString *str2 = str; [str release]; [str2 release]; //---this is not OK as you do not own str2---
Attempting to release
str2
will result in a runtime error because you cannot release an object not owned by you.
We can actually use [str2 release]
if that is called before [str release]
. If we do that, then the line [str release]
will cause an error because now str
as well as str2
are both dangling pointers, and supposedly when release
was sent to the object the first time, the reference count became 0, and dealloc
was called immediately, and the memory was freed by the C function free()
.
Is the above correct, or maybe there is something else to be corrected?
Don't think of it in terms of managing memory, but in terms of object ownership. You obtain ownership of an object when you allocate it, retain it, or copy it. You are responsible for releasing exactly the objects you own, not others.
In your example the assignment to str2
does not take ownership of the object, but if you really need a second "owning" reference to it, then you ought to do [str2 retain]
, after which it is not an error to do [str release]; [str2 release];
. This is also what would happen automatically using ARC, unless you annotated str2
as a weak reference. (Of course in this simple case the unnecessary retain/release could be optimized away internally by the compiler.)
Your guess is correct: The book uses fuzzy language (even though the implications are correct) in an effort to simplify pointers away:
You own the object that str
and str2
point to.
This of course means that you can only release the object once (or rather however often it was retained - once in your example, implicitly, by alloc
), and whether you do so through str
or str2
(or any other means) is insignificant.
In practice, you should treat your variables as if you owned them, though. This makes it much easier to keep track of retain/release pairs, and you cannot rely on the fact that nobody changed the value of one of these variables somewhere in between.
It is good practice (but not necessary) to set all variables that point to a deallocated instance to nil
afterwards.
To delve a bit into the technical details (which really should be treated as what they are: Implementation details; artifacts of a private API):
Technically, nobody owns the object. The object has a counter of the number of times it was retained (which you can find out by calling anObject retainCount
- but you shouldn't, not least because some objects have a bogus retainCount, and because it's really none of your concern). When an object is alloc
ed, its retainCount is 1. Every time it is sent retain
("it is retained"), its retainCount goes up by 1, and every time it is sent release
("it is released"), its retainCount is decreased by 1.
Once the retainCount of an object reaches zero, it is deallocated (and its dealloc
method is called).
Who sent all those retain
/release
messages (and through which variables) is not important.
Again: These are implementation details. They're artifacts of the way Objective-C/Cocoa do their memory management. Treat them like any private API: It's good to be curious, but never rely on internals. Only ever use the public API (in this case, retain
/release
and autorelease pools) in production code.
NOTE: Some objects (for instance some singletons) override the default retain/release methods. Never trust the retainCount
you get from an object, other than for curiosity (look at the retainCount of [UIColor clearColor]
for instance).
For more thoughts on this topic, this question and its answers are probably a nice summary/starting point.
That said, consider switching to ARC, which will rid you of almost all memory management troubles.
I thought ownership is by object, not variable or pointer... so we can't say we "own str" or "own str2"... we own an object, which is pointed to by either str or str2, and if we use [str release] or [str2 release], it is all the same.
This is correct.
I think what the author means by "we own str" ist that you own that string instance. Not the pointer or the variable. You could theoretically release the object using an other pointer. But it's generally a better idea to release using the variable you used to initialize the object.
I think the other answers are wrong or incomplete.
Ownership is defined by who releases a resource. An object doesn’t (usually) own itself, it is owned.
Again: the owner is whoever is responsible for releasing the memory.
In your code, str
has declared its ownership of the object, str2
has not. In order for str2
to also own the object (to share str
’s ownership), you’d need to retain
it:
[str2 retain];
Now you could later say,
[str2 release];
to relinquish str2
’s claim to ownership, and the same goes for str
.
On the other hand, with ARC, all (reference-counting) pointers to a resource are its shared owners. In this scenario, all pointers are responsible for keeping track of the object reference count, and releasing the object once they determine that they are the sole owners and go out of scope.
To reiterate: Ownership is not by object. Ownership is by pointers to an object, and the owner of those pointers, but only if those pointers might be released in some scenario. Pointers are non-owning if there is no scenario in which they would release the resource. In this case, they are called weak.
The concept of a weak pointer would make no sense if objects owned themselves (since all pointers would be weak).
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With