2010-01-12 23 views
3

我正在使用XMLParser解析一些XML数据,它使用NSMutableString * resultString来存储标记字符。在每个( - parser:didStarElement ...)方法中,我分配并初始化resultString-ivar。内存泄漏NSMutableString appendString

- (void)parser: (NSXMLParser *)parser didStartElement: (NSString *)elementName namespaceURI: (NSString *)namespaceURI qualifiedName: (NSString *)qName attributes: (NSDictionary *)attributeDict { 
// Alot of if-statements to sort subtags 
// /.../ 
    resultString = [[NSMutableString alloc] init]; 
    recordResults = YES; 
} 

将字符串添加到解析器中:foundCharacters-method。我在某处读取自动释放对象,比如appendString中的字符串可能导致内存泄漏的图像。所以我加了一个本地autorelease池,以确保它得到倒掉马上(的行为没有改变,虽然):

- (void)parser:(NSXMLParser *)parser foundCharacters:(NSString *)string { 
NSAutoreleasePool *pool = [[NSAutoreleasePool alloc] init]; 
if(recordResults) { 
    [resultString appendString: string]; 
} 
[pool drain]; 
} 

在解析器:didEndElement ......我终于释放和无出resultsString:

-(void)parser:(NSXMLParser *)parser didEndElement:(NSString *)elementName namespaceURI:(NSString *)namespaceURI qualifiedName:(NSString *)qName { 

    // Alot of if statements to handle differnt tags 
    // each of which has the structure of the last else-statement 
    // In other words, I am pretty sure I've covered every possible 
    // case to prevent the resultString from 
    // not getting released and niled out 
    if(...) { 
      ... 
} 
    else if(...) { 
      ... 
    } 
else { 
    if(resultString != nil) { 
     [dataDict setObject: resultString forKey: elementName]; 
     [resultString release]; 
     resultString = nil; 
    } 
} 

仪器泄漏工具标记解析器:foundCharacter方法作为内存泄漏的来源,所以我想知道这是否是由appendString引起的。或者如果你能在这段代码中找到一些出错的东西。 这是一个相当渴望内存的应用程序,解析iPhone上的相当多的,有时是中等大小的XML文件,所以我的问题是如何找到解决办法,如果在这种情况下NSMutableString appendString不适合...

在此先感谢!

回答

3

如果结束标记丢失,您将有内存泄漏。最好在parserDidStartDocument中有任何分配:并且在parserDidEndDocument:中解除分配,因为这些保证是成对的。而不是在didStartElement中分配resultString,您只需在那里截断它。

+0

我不确定parserDidEndDocument是否在解析错误时被调用,但这应该很容易测试。 – ergosys 2010-01-13 00:29:23

+0

好点!应该做一些性能改进,对,因为我不必为每个标记分配和初始化NSMutableString? 并截断你只是建议设置[resultString setString:@“”]? – jollyCocoa 2010-01-13 06:48:00

+0

我试过你的这个解决方案。它似乎解决了这个问题。非常感谢! 我非常幸运能够使用XML来处理所有关闭标记。但是,如果没有,我想我可以实现解析器:parseErrorOccured或处理这些... – jollyCocoa 2010-01-13 08:09:10

0

我不认为你可以知道appendString是否使用autorelease或不是,因为该方法改变它的对象而不是返回一个新的对象。换句话说,因为它自身在变化,所以你不需要为它的内存管理负责。您也不拥有string,因此您不必释放或自动释放它。

检查了这一点:http://developer.apple.com/mac/library/documentation/cocoa/Conceptual/MemoryMgmt/Articles/mmRules.html#//apple_ref/doc/uid/20000994-BAJHFBGH

这可能会澄清的事情,但随着自动释放了关键的是,“新”的对象比分配/初始化areautoreleased以外的东西回来。在这种情况下,appendString不会返回新对象,并且可以简单地保留字符串,将其传递给解析器回调,稍后由调用者释放,所以谁知道是否自动释放。

当你需要自动释放某些东西的时候,是当你有一个使用alloc/new/copy的函数/方法,然后返回该对象时,函数本身无法将它释放。

+0

我同意我也可以省略autorelease池。我在这里得到了一个关于stackoverflow的提示,虽然我不明白为什么它应该有所帮助,但我试了一下。我试图在第一篇文章中提到,但显然还不够清楚。 – jollyCocoa 2010-01-13 06:45:17

0

自动释放缓冲池没有任何作用,因为您不会自动释放任何对象 - 您正在将可变字符串分配到一个位置,并将其释放到另一个位置。 “appendString”对MutableString的保留计数没有任何作用。

至于泄漏,这里是处理 - 泄漏告诉你,内存泄漏是分配。所以这意味着在分配内存的部分中一切正常 - 不好的是,在其他地方,保留在该方法中的内存应该被释放,但事实并非如此。

因此,在某些时候,似乎你从dataDict中取出resultString放置它,保留它并且不释放它(在我看来,像释放它一样在解析过程中可以,所以不会是罪魁祸首)。要验证这是如此,更改插入的字符串是::

[dataDict setObject:[[resultString copy] autorelease] forKey: elementName]; 

并泄漏应该告诉你泄漏是在那里。为了帮助追踪泄漏,无论何时从dataDict中提取一个字符串,您都可以[复制]它,然后您将更接近泄漏字符串的确切代码。

基本上泄漏就像一个有人死亡的神秘书的开幕。你可以找出凶手是谁 - 或者在泄漏情况下,谁应该杀人,但没有解决。

+0

是的,你是对的。然而。它也没有真正伤害,我仍然有泄漏,所以我仍然困惑。 – jollyCocoa 2010-01-13 06:46:34

+0

我添加了一个关于哪些泄漏事实真实地告诉我我的回复的消息,对不起,我没有在那天晚上了解更多的细节,但当时我太急了。 – 2010-01-14 00:33:23