内存泄漏与NSMutableString appendString

时间:2010-01-12 23:57:51

标签: iphone memory string append memory-leaks

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

-  (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中的字符串可能会导致内存泄漏的图像。所以我添加了一个本地自动释放池,以确保它立即耗尽(尽管行为没有变化):

- (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;
    }
}

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

提前致谢!

3 个答案:

答案 0 :(得分:3)

如果缺少结束标记,则会发生内存泄漏。最好在parserDidEndDocument:中的parserDidStartDocument:和deallocations中进行任何分配,因为这些分配保证是配对的。而不是在didStartElement中分配resultString,你只需在那里截断它。

答案 1 :(得分:0)

我认为您不知道appendString是否正在使用autorelease,因为该方法会更改其对象而不是返回新对象。换句话说,因为它正在改变自己,所以你不负责它的内存管理。您也不拥有string,因此您无需发布或自动发布它。

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

这可能会澄清一些事情,但自动释放的关键在于,除了alloc / init之外的其他东西返回的“新”对象已经过时。在这种情况下,appendString不会返回任何新对象,并且可以简单地保留字符串,传递给解析器回调,然后由调用者稍后释放,这样谁知道是否自动释放。

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

答案 2 :(得分:0)

自动释放池无效,因为您没有自动释放任何对象 - 您在一个位置分配可变字符串,在另一个位置释放它。 “appendString”对MutableString的保留计数完全没有任何作用。

至于泄密,这是交易 - 泄漏告诉你内存泄漏分配。这意味着在分配内存的部分中一切正常 - 不行的是,在其他地方,该方法中保留的内存应该被释放而不是。

所以在稍后的某个时候,你似乎从dataDict中取出了resultString,保留它并且不释放它(在我看来,就像你在解析时释放它一样,这样就不会成为罪魁祸首)。要验证是这样,请将字符串的插入更改为::

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

泄漏应告诉你泄漏是否存在。为了帮助追踪泄漏,每次从该dataDict中提取字符串时,您都可以[复制]它,然后您将更接近泄漏字符串的确切代码。

基本上泄漏就像一本神秘书的开篇,有人死了。由你来决定杀手是谁 - 或者在泄漏的情况下,谁应该做杀人但是没有绕过它。