views:

250

answers:

1

Hello, I'm at my first experiences with iPhone development. I wrote some basic code to test the NSScanner class, and now I was looking into the Leaks tool. It seems that this code is leaking, when in the detailed stack I double-click my last call (before Apple's stuff), the incriminated line is the commented.

Can anyone help me to understand why this is leaking? from a logical point of view the result is what I expect, and I do not formally alloc anything myself (except for the xmlblock variable, which is btw autoreleased), so I would not expect the need to release anything... where I'm wrong? :-)

+(NSSet *)extractXMLSectionsWithTag:(NSString *)tag fromString:(NSString *)source firstOnly:(BOOL)firstOnly
{
 if (!source)
 return nil;
 NSScanner *scanner = [NSScanner scannerWithString:source];
 NSString *openingToken = [NSString stringWithFormat:@"<%@", tag];
 NSString *closingToken = [NSString stringWithFormat:@"</%@>", tag];
 NSMutableSet *sections = [NSMutableSet set];
 NSCharacterSet *majorChar = [NSCharacterSet characterSetWithCharactersInString:@">"];

 while (![scanner isAtEnd]) {
 NSString *xmlBlock = [[[NSString alloc] init] autorelease];
 [scanner scanUpToString:openingToken intoString:NULL];
 [scanner scanString:openingToken intoString:NULL];
 [scanner scanUpToCharactersFromSet:majorChar intoString:NULL];
 [scanner scanCharactersFromSet:majorChar intoString:NULL];
 [scanner scanUpToString:closingToken intoString:&xmlBlock];
 if (![xmlBlock isEqualToString:@""]) { // Leaking line
  [sections addObject:xmlBlock];
  if (firstOnly) {
   break;
  }
 }
 }
 return [sections copy];
}
+1  A: 

I'm pretty sure the leak is caused by returning [sections copy], from a method like that you are supposed to return an autoreleased string - not a retained one.

In XCode choose the "Build & Analyze" option and see what it says about this code.

Kendall Helmstetter Gelner
Yes that was the problem, many thanks, it wasn't clear to me thay the copy message creates a retained object (I was fooled by thinking that I was not calling any init message, so it was not my duty to release... but copying is actually a creaton, of course). I changed the last line to "return [[sections copy] autorelease], and the leak does not show up anymore!
Andy
Actually, you can just return "sections" since it is autoreleased already. No need to copy and then autorelease, as it has the same effect...
Kendall Helmstetter Gelner
The final copy was (in my mind) to return an immutable version, to avoid any overhead the mutable version could carry on... is this wrong or useless?
Andy
It's not exactly wrong, it's just a wash compared to the extra resources you use to create the copy... however that said I do usually use copy on the other side, at least for NSString properties. There I like to have a clearer picture when the string I am using was really allocated. Because you mostly return autoreleased objects I like to leave it up to the caller to decide if it's worth the expense of making a copy, the caller does not know what you are returning is mutable so there's no danger there.If the value were meant to be accessed by different threads later on, then I would copy.
Kendall Helmstetter Gelner
Got it, I has a suspect about the overhead of copying, but the suggestion to leave the caller decide seems a very good design approach, thanks!
Andy