Re: NSMutableDictionary not sending release message to contained objects at dealloc time
Re: NSMutableDictionary not sending release message to contained objects at dealloc time
- Subject: Re: NSMutableDictionary not sending release message to contained objects at dealloc time
- From: Greg Titus <email@hidden>
- Date: Fri, 11 Apr 2003 08:15:09 -0700
On Friday, April 11, 2003, at 03:57 AM, Greg Hurrell wrote:
El Friday, 11 Apr, 2003, a las 05:05 Australia/Adelaide, Jonathan E.
Jackel escribis:
It's correct, and it's not leaking.
I don't think so!
Well, think about it a little more, because Jonathan is correct. :-)
dict continues to exist throughout the scope of your code. You
create it,
add it to an array, then remove it from the array. Its retain count
is
incremented, then decremented.
At allocation time, its retain count is 1, even though it is an
autoreleased object. It is part of the autoreleased pool, so when the
autorelease pool is deallocated, it will send a release message to the
dictionary and it will go away (because then its retain count will be
zero).
From the Cocoa docs: "You add an object to an autorelease pool so it
will receive a release message-and thus might be deallocated-when the
pool is destroyed."
Yes, you are correct here.
None of that affects the objects in dict. Their retain count stays
the
same, as you have demonstrated.
It shouldn't. The contents of the dictionary should be sent a release
message when the dictionary itself is releaed, to balance the retain
message they are sent when added to the dictionary.
No, absolutely not. The contents of the dictionary should be sent a
release message when the dictionary itself is _dealloced_, to balance
the retain message they are sent when added to the dictionary. If you
retain the dictionary 10 times, it doesn't retain each object inside
the dictionary 10 times - those objects were retained _once_ when they
were added to the dictionary in the first place. If you then release
the dictionary 10 times, each object inside the dictionary is
unaffected. It is only when the dictionary itself is deallocated
(retain count goes to zero) that it is emptied and every object inside
it receives a single release.
Again from the Cocoa docs: "Each corresponding value object receives a
retain message to ensure that it won't be deallocated before the
dictionary is through with it" and "When an object is removed from an
array, it's sent a release message" (note I can't find a quote exactly
like this for NSDictionary, only for NSArray, but I believe these two
collection classes behave the same way with respect to retain/release
of member objects).
Note how it says "when an object is removed from an array".
This is how I think it works (should work):
- allocate object (retain count 1, regardless of whether autoreleased)
- add object to collection (retain count 2)
- remove object from collection (retain count 1)
- deallocate object when retain count hits 0 again (either via
autorelease or explicit release, depending on method with which object
was obtained)
Yep, this is exactly right. But in your sample code "obj" has not been
removed from the dictionary yet. Look:
MYObject *obj = [[MYObject alloc] init];
obj is allocated, retain count is 1.
NSMutableDictionary *dict = [NSMutableDictionary
dictionaryWithObjectsAndKeys:obj, @"Key", nil];
dict is allocated and then autoreleased, retain count is 1, and it is
in the autorelease pool.
obj is added to the dict and retained, retain count is 2.
NSMutableArray *arr = [[NSMutableArray arrayWithObjects:dict, nil];
dict is added to the array, so its retain count is now 2. It is still
in the autorelease pool.
NSLog(@"Retain count on obj is %d", [obj retainCount]); // count is
2
(correct)
Right.
// remove the dictionary, which should send release to obj as well
[arr removeObjectAtIndex:0];
Wrong, removing the dictionary sends a release to _the dictionary_.
dict has its retain count reduced to 1. It is still in the autorelease
pool.
obj is unaffected because it is still inside dict. Its retain count
remains 2.
NSLog(@"Retain count on obj is %d", [obj retainCount]); // count is
still 2 (INCORRECT!)
Nope, this is correct.
Now, later, when the autorelease pool is cleaned up, dict will be
released again. This will reduce its retain count to zero, which will
cause it to dealloc itself, which will release its contents. Then, and
only then, obj's retain count will go down to 1.
Hope this helps,
- Greg
_______________________________________________
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.