Re: Proper retain/release etiquette
Re: Proper retain/release etiquette
- Subject: Re: Proper retain/release etiquette
- From: Marcel Weiher <email@hidden>
- Date: Tue, 23 Jul 2002 09:25:15 +0200
On Thursday, January 1, 1970, at 02:26 Uhr, Roarke Lynch wrote:
On Monday, July 22, 2002, at 09:05 PM, Chris Anderson wrote:
1. If my code alloc's an object, it is implicitly retained by me and
must be
subsequently released. (Said another way, if I did [[[Foo alloc] init]
retain] I would have to release the object twice for it to deallocate.)
yes, init, copy and retain all increase an objects reference count
by one.
-copy and -retain: yes
-init: no!
It is the +alloc that 'increases' the objects reference count, or
rather: initializes it.
It is good for any method (with the exception of your init and dealloc
methods) to have an equal count of (init, copy or mutableCopy, retain)
and (release, autorelease).
(adjust as needed)
2. The right place to release contained objects is in the dealloc
method.
They should be released and then a [super dealloc] should be done.
Yes, unless you are changing the 'nature' of a contained object. i.e
- (void)setVal:(id)newVal {
[val autorelease];
val = [newVal copy];
}
That doesn't affect the part about releasing in your dealloc.
3. If I got a new object from the system frameworks via any method but
'alloc', it will get implicitly autoreleased, so I have to retain it
if I
want it to persist beyond the next RunLoop cycle.
If the object is created using a convience method, i.e [NSArray
arrayWithObjects:objOne, objTwo, nil] the object (if the method is written
correctly is autoreleased before it is returned to you. So you should
not release it.
It may or not be autoreleased, all you need to know and can rely on is
that it is not owned by you and you need to retain it if you want it
keep it around, and do *not* need to release it if you don't want to
keep it around. Do not rely on such methods actually returning
autoreleased objects.
4. It's OK to release objects that were allocated by another thread
(assuming that the other thread properly retained what it still needs.)
I find it generally safer not to, but if you do. Call autorelase
not release. This delays the release call until the end of the run
loop, allowing the object to still be used in other areas of the
app.
This is probably not a good idea, because you have introduced a
timing-dependent bug: the object may be deallocated while still in use
depending on how quickly you get done with event processing in this
thread.
If a thread wishes to use such an object, *it* should retain/autorelease
it so it sticks around until that thread is done with it.
5. Similarly, auto-release pools in multiple threads won't
auto-collide even
if they contain some of the same objects.
I believe that there should generally only be one autorelease
pool, special cases excluded.
No. Each thread has at least one autorelease pool. Having sub-pools,
though often not necessary, is not something to be discouraged.
7. If I hand an object to a system framework method, the docs for it
ought
to tell me explicitly if the framework is ever then going to release or
retain that object (which it usually doesn't.)
They generally don't modify your object (including its reference
count) if they are written correctly.
With some exceptions, the framework will retain your object (increase
its reference count) if it stores the reference somewhere.
8. A "retain chain" must not loop - i.e. Object ownership should be
uni-directional.
Yes. If you have a retain-cycle, you have a memory leak. You should
try to avoid them in the design phase by finding a part of the cycle
that doesn't need to be retained because you know there is a retain
(Example: subviews don't retain their superviews because they know they
are being retained by their superview).
If you cannot do this by design, you will have to find a way to break
the cycle or live with the leak.
9. One should not attempt to re-use objects by re-initing them.
no.
No which way? Anyway, you can design your objects to be
re-initializable. I do it all the time, and the MPWObjectCache ( in
MPWFoundation ) is designed to work with re-initializable objects. I
wouldn't rely on other objects to be re-initializable.
10. It is bad practice to do: id bar = [Foo alloc]; [bar init];
because init
might hand back a different object than the original alloc did.
Yes. Or even return nil. Another factor is reading the code. id bar =
[[Foo alloc] init]; is the idiomatic way of doing it, so a reader will
stumble over your code and wonder why you did it that way. If there is
no reason, the reader might be reasonably worried about the rest of the
code.
This is programmatically similar to nesting the two i.e id bar =
[[Foo alloc] init]. So i think it makes no difference.
Yes it does. Think about -init returning nil.
Marcel
_______________________________________________
cocoa-dev mailing list | email@hidden
Help/Unsubscribe/Archives:
http://www.lists.apple.com/mailman/listinfo/cocoa-dev
Do not post admin requests to the list. They will be ignored.