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: Phill Kelley <email@hidden>
- Date: Sat, 12 Apr 2003 12:06:48 +1000
At 8:32 AM +0930 12/4/03, Greg Hurrell wrote:
>
Fair enough... My misunderstanding hinged on my belief that collection
>
classes like NSMutableDictionary and NSMutableArray would behave the
>
same.
>
>
Both send a retain as objects are added.
>
>
Yet while array sends a release when objects are removed, the dict only
>
sends a release when it itself is deallocated (according to you, and I
>
defer to your experience on this one!) Why the discrepancy in behaviour?
Consider the following example (you may wish to create a new "foundation
tool" project in PB and paste this code into the main.m template).
#import <Foundation/Foundation.h>
#define key @"KEY"
void test1 () // test removeObjectForKey
{
NSAutoreleasePool * pool = [[NSAutoreleasePool alloc] init];
NSMutableDictionary* dict = [[NSMutableDictionary alloc] init];
NSString* s = [[NSString alloc] initWithString:@"Example"];
NSLog(@"1.1: dict=%d, s=%d",[dict retainCount],[s retainCount]);
[dict setObject:s forKey:key];
NSLog(@"1.2: dict=%d, s=%d",[dict retainCount],[s retainCount]);
[dict removeObjectForKey:key];
NSLog(@"1.3: dict=%d, s=%d",[dict retainCount],[s retainCount]);
[pool release];
NSLog(@"1.4: dict=%d, s=%d\n\n",[dict retainCount],[s retainCount]);
}
void test2 () // test dictionary release
{
NSAutoreleasePool * pool = [[NSAutoreleasePool alloc] init];
NSMutableDictionary* dict = [[NSMutableDictionary alloc] init];
NSString* s = [[NSString alloc] initWithString:@"Example"];
NSLog(@"2.1: dict=%d, s=%d",[dict retainCount],[s retainCount]);
[dict setObject:s forKey:key];
NSLog(@"2.2: dict=%d, s=%d",[dict retainCount],[s retainCount]);
[dict release];
NSLog(@"2.3: s=%d",[s retainCount]);
[pool release];
NSLog(@"2.4: s=%d\n\n",[s retainCount]);
}
void test3 () // test dictionary autorelease
{
NSAutoreleasePool * pool = [[NSAutoreleasePool alloc] init];
NSMutableDictionary* dict = [[NSMutableDictionary alloc] init];
NSString* s = [[NSString alloc] initWithString:@"Example"];
NSLog(@"3.1: dict=%d, s=%d",[dict retainCount],[s retainCount]);
[dict setObject:s forKey:key];
NSLog(@"3.2: dict=%d, s=%d",[dict retainCount],[s retainCount]);
[dict autorelease];
NSLog(@"3.3: dict=%d, s=%d",[dict retainCount],[s retainCount]);
[pool release];
NSLog(@"3.4: s=%d\n\n",[s retainCount]);
}
int main (int argc, const char * argv[]) {
NSAutoreleasePool * pool = [[NSAutoreleasePool alloc] init];
NSLog(@"Test removeObjectForKey"); test1();
NSLog(@"Test dictionary release"); test2();
NSLog(@"Test dictionary autorelease"); test3();
[pool release];
return 0;
}
Running the above program produces the following output:
2003-04-12 10:06:31.839 example[814] Test removeObjectForKey
2003-04-12 10:06:31.841 example[814] 1.1: dict=1, s=1
2003-04-12 10:06:31.841 example[814] 1.2: dict=1, s=2
2003-04-12 10:06:31.841 example[814] 1.3: dict=1, s=1
2003-04-12 10:06:31.841 example[814] 1.4: dict=1, s=1
2003-04-12 10:06:31.841 example[814] Test dictionary release
2003-04-12 10:06:31.841 example[814] 2.1: dict=1, s=1
2003-04-12 10:06:31.841 example[814] 2.2: dict=1, s=2
2003-04-12 10:06:31.842 example[814] 2.3: s=1
2003-04-12 10:06:31.842 example[814] 2.4: s=1
2003-04-12 10:06:31.842 example[814] Test dictionary autorelease
2003-04-12 10:06:31.842 example[814] 3.1: dict=1, s=1
2003-04-12 10:06:31.842 example[814] 3.2: dict=1, s=2
2003-04-12 10:06:31.842 example[814] 3.3: dict=1, s=2
2003-04-12 10:06:31.842 example[814] 3.4: s=1
Analysis. In each case:
1. We dynamically allocate a dictionary and a string.
Step n.1 shows that each has a retain count of 1, as expected.
2. We add the string to the dictionary:
Step n.2 shows that the string has a retain count of 2, as expected.
3. We remove the string in some manner:
Step 1.3 uses removeObjectForKey. The string's retain count goes to 1,
as expected.
Step 2.3 releases the dictionary, which implies a release sent to each
member of the dictionary. The string's retain count goes to 1, as expected.
Step 3.3 autoreleases the dictionary. The dictionary still exists and all
its members are intact. The string's retain count is still 2, as expected.
4. We release the local autorelease pool:
Steps 1.4 & 2.4: neither the dictionary nor the string is affected by the
autorelease pool, so the retain counts do not change. As expected.
Step 3.4: When the autorelease pool is released, it sends a release to
the dictionary which, in turn, sends a release message to each of its
members. The string's retain count goes to 1, as expected.
Now, call me mad, but it seems to me that everything is behaving correctly.
Further, if you change the code to use an NSMutableArray and substitute the
appropriate methods (addObject & removeObjectAtIndex), you get exactly the
same behaviour.
Regards, PK
_______________________________________________
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.