11

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 for str, so you own str. Therefore, you need to release it when it’s no longer needed. However, str2 is simply pointing to str, so you do not own str2, meaning you need not release str2 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?

Jeremy L
  • 3,770
  • 6
  • 41
  • 62
  • 2
    +1, but consider using [ARC](http://developer.apple.com/library/ios/#releasenotes/ObjectiveC/RN-TransitioningToARC/Introduction/Introduction.html) in new code. – rid May 13 '12 at 13:05
  • You are right. The book is either very confusing or wrong at all. – Manlio May 13 '12 at 14:24
  • 1
    What book is this, by the way? – fzwo May 13 '12 at 15:25

5 Answers5

5

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.)

Arkku
  • 41,011
  • 10
  • 62
  • 84
3

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 alloced, 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.

Community
  • 1
  • 1
fzwo
  • 9,842
  • 3
  • 37
  • 57
  • The concept of ownership is in fact the correct way to reason about reference counting, _not_ the actual numbers involved. `str` is an owning reference, and `str2` is not, despite them pointing to the same object. It is semantically incorrect to send `release` to `str2` because you did not obtain that reference via an ownership-granting method. – jscs May 13 '12 at 20:03
  • @Jacques I hope I've made it clear that the actual retainCount is nothing but a curious implementation detail. You are right though that it is best practice to release objects through the same variables you retained them through (not least because in non-trivial examples one of the variables might now point to a different object); nevertheless, ownership is "only" a concept, not a technical truth, IMHO. Your very nice question and the answers at http://stackoverflow.com/questions/5784084/calling-retaincount-considered-harmful might satisfy some curiousity about this as well. – fzwo May 13 '12 at 22:02
  • Well, you prefaced the second half of your answer, where you talk about retain counts and using `retainCount` with "to get even more correct", which it isn't. The "technical truth" of the reference count is (as you said) none of the user's concern -- ownership is the higher level where the meaning resides and where decisions should be made. At that level, it absolutely _does_ make a difference which pointer you use to send `release`. It's only at the lower level, which you should (generally) be ignoring, that you can send `release` via any reference you like. – jscs May 13 '12 at 22:37
  • @Jacques I don't want to leave false information here, so I've edited my answer. Care to comment? – fzwo May 14 '12 at 07:41
2

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.

DrummerB
  • 39,814
  • 12
  • 105
  • 142
  • Why would it be better to release the object in the memory using the pointer that created it? The two pointers are equal, so the choice is yours which one you want to use to release the object. – Hidde May 13 '12 at 13:16
  • 1
    @Hidde: It doesn't matter technically, but it makes it easier to keep track of retain/release if you keep some discipline in using it. – fzwo May 13 '12 at 13:22
  • OK, that's true. But, if we are talking about good programming habits, why would you make two pointers to the object? If there is any reason to do that, maybe there is also a reason for releasing the object using the second pointer. – Hidde May 13 '12 at 13:25
  • 1
    You are right, there might be some corner cases. But as I said, "generally" it's better to release using the same variable. – DrummerB May 13 '12 at 13:31
  • This answer is misleading. See my answer for a clarification. – Konrad Rudolph May 13 '12 at 18:56
1

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).

Konrad Rudolph
  • 530,221
  • 131
  • 937
  • 1,214
0

If you release either str or str2, the memory location str and str2 points to is freed. So, you only have to call str or str2, not both, because they point to the same memory location.

I don't understand what you mean by 'owning' a variable, as far as I know a pointer can point to a piece of space in the memory, and nothing more.

Hidde
  • 11,493
  • 8
  • 43
  • 68
  • i use the phrase "own a variable" because the author seems to suggest that we "own `str`" and not own `str2` – Jeremy L May 13 '12 at 13:09
  • The concept of "owning an object" is widely used in programming to refer to the responsibility for the space in memory occupied by an object. If you "own" an object, you're responsible for cleaning up its memory. – rid May 13 '12 at 13:11
  • That way... I think this is confusing, because `str2` can do exactly the same with the object it points to as `str` can. If we call [str2 release], it means exactly the same as `[str release]`. If you are using 'own' referring to the action of reserving space in the memory for the creation of an object, it seems that one pointer has more power/privileges on the object. It does not, so it's confusing. – Hidde May 13 '12 at 13:14