• Open Menu Close Menu
  • Apple
  • Shopping Bag
  • Apple
  • Mac
  • iPad
  • iPhone
  • Watch
  • TV
  • Music
  • Support
  • Search apple.com
  • Shopping Bag

Lists

Open Menu Close Menu
  • Terms and Conditions
  • Lists hosted on this site
  • Email the Postmaster
  • Tips for posting to public mailing lists
Re: NSMutableDictionary not sending release message to contained objects at dealloc time
[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index]

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.

  • Follow-Ups:
    • Re: NSMutableDictionary not sending release message to contained objects at dealloc time
      • From: Greg Hurrell <email@hidden>
References: 
 >Re: NSMutableDictionary not sending release message to contained objects at dealloc time (From: Greg Hurrell <email@hidden>)

  • Prev by Date: Cocoa Window Not Activated When Called From Carbon Application
  • Next by Date: Optimizing NSMutableDictionary Speed
  • Previous by thread: Re: NSMutableDictionary not sending release message to contained objects at dealloc time
  • Next by thread: Re: NSMutableDictionary not sending release message to contained objects at dealloc time
  • Index(es):
    • Date
    • Thread