PDA

View Full Version : Cannot release a mutableCopy despite having just created it




peptidyl
Dec 10, 2009, 05:22 AM
Hello all - firstly, a thanks to all of you in advance for your help.

I tried googling this problem to no avail. The problem is, I create a mutableCopy of an NSArray and assign it to a NSMutableArray, and quickly assign it to something else and then try to release it. The debugger tells me that it stalls on the release, even though I've checked that retainCount = 1. Here's the code for the entire method:

+ (void)setUpChapters {

NSMutableArray *chapters = [NSMutableArray array];
NSMutableArray *componentsFullList = [NSMutableArray array];

[componentsFullList addObject:@"Introduction\\A few brief words\\intro.html\\introduction.a.few.brief.words"];
[componentsFullList addObject:@"Cells\\A quick look at bacteria\\cells.1.html\\bacteria.LUCA.eukaryote.ribosome"];
[componentsFullList addObject:@"\\Testpage\\cells.1.html\\test.delete.me"];

Chapter *chapter = nil;

if (chapter == nil) {
for (NSString *aComponent in componentsFullList) {
NSArray *aComponentsList = [[aComponent componentsSeparatedByString:@"\\"] copy];
NSLog(@"%@",[[NSNumber numberWithInt:[aComponentsList retainCount]] stringValue]); // returns 1
NSArray *componentsList = aComponentsList;
[aComponentsList release]; // here it stalls
chapter = [[Chapter alloc] initWithName:[componentsList objectAtIndex:0]];
[chapters addObject:chapter];
[chapter release];
if ([componentsList objectAtIndex:1]!=NULL) {
Section *section = [[Section alloc] initWithName:[componentsList objectAtIndex:1]];
[chapter addSection:section];
[section release];
}
TextBody *textBody = [[TextBody alloc] initWithHTMLString:[componentsList objectAtIndex:2]];
[chapter addTextBody:textBody];
[textBody release];

// opening the relevant file to parse into keywords
NSString *bundlePath = [[NSBundle mainBundle] bundlePath];
NSURL *bundleBaseURL = [NSURL fileURLWithPath: bundlePath];
NSURL *bundleBaseURLWithFile = [NSURL URLWithString: [componentsList objectAtIndex:2] relativeToURL: bundleBaseURL];

NSError *error = nil;
NSString *totalDataString = [[NSString alloc] initWithContentsOfURL:bundleBaseURLWithFile encoding:NSUTF8StringEncoding error:&error];
NSLog (@"%@", [error localizedDescription]);

NSCharacterSet *splitterCharacters = [NSCharacterSet characterSetWithCharactersInString:@" .,!?@$%^&*()_+-=[]{}'\"/~<>"];
NSMutableArray *keywordList = [[totalDataString componentsSeparatedByCharactersInSet:splitterCharacters] mutableCopy];
for (NSString *individual in keywordList) {
Keywords *keyword = [[Keywords alloc] initWithString:individual];
[chapter addKeywords:keyword];
[keyword release];
}
[keywordList autorelease];

}
}

for (Chapter *aChapter in chapters) {
chapter = aChapter;
}

knownChapters = chapters;


}


Thank you in advance.



dejo
Dec 10, 2009, 09:56 AM
The problem is, I create a mutableCopy of an NSArray and assign it to a NSMutableArray, and quickly assign it to something else and then try to release it.
Except nowhere in the code you supplied do you actually do that. keywordList is assigned via mutableCopy but then you use it as the basis of a for-each loop and then autorelease it.

kainjow
Dec 10, 2009, 12:08 PM
NSArray *aComponentsList = [[aComponent componentsSeparatedByString:@"\\"] copy];
NSArray *componentsList = aComponentsList;
[aComponentsList release]; // here it stalls
chapter = [[Chapter alloc] initWithName:[componentsList objectAtIndex:0]];

Briefly looking at the code, I don't see why that would be a problem. componentsSeparatedByString returns an autoreleased object, and then you copy it. copy then will retain it, and then you release it, so we're back to the autoreleased object which doesn't get released until the next run loop iteration (after all your code is done executing).

BTW the NSNumber in this line is unnecessary:
NSLog(@"%@",[[NSNumber numberWithInt:[aComponentsList retainCount]] stringValue]);
Just do this:
NSLog(@"%d",[aComponentsList retainCount]);

jnic
Dec 10, 2009, 12:24 PM
even though I've checked that retainCount = 1

http://developer.apple.com/iphone/library/documentation/Cocoa/Reference/Foundation/Protocols/NSObject_Protocol/Reference/NSObject.html#//apple_ref/occ/intfm/NSObject/retainCount

Important: This method is typically of no value in debugging memory management issues. Because any number of framework objects may have retained an object in order to hold references to it, while at the same time autorelease pools may be holding any number of deferred releases on an object, it is very unlikely that you can get useful information from this method.

PhoneyDeveloper
Dec 10, 2009, 12:33 PM
The debugger tells me that it stalls on the release

What does this mean?