XML Parser中的内存泄漏

时间:2010-01-30 22:52:00

标签: iphone objective-c memory-management memory-leaks nsxmlparser

我使用NSXMLParser来解析XML文档。我有以下功能(其中包括):

- (void) parserDidStartDocument:(NSXMLParser *)parser {

    // Init tempString
    tempString = [NSMutableString string];

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

        // save gained data for element "date"
        if ([elementName isEqualToString:@"date"])
            [entryDict setObject:[tempString copy] forKey:kXMLDictDateKey];

        [tempString setString:@""];
    }


    //
    // Character Handling
    //
    - (void)parser:(NSXMLParser *)parser foundCharacters:(NSString *)string {
        [tempString appendString:[[XMLParser alloc] stripUnwantedStringChars:string]]; //Just strips tabs and linebreaks and the returns the string
    }

tempString是一个具有以下属性的实例变量:

@property (nonatomic, retain) NSMutableString *tempString;

tempString不必在dealloc中释放,因为它是使用便捷方法启动的,因此它会自动分配给自动释放池。我还尝试使用alloc,init方法,但结果相同。所以这就是我所做的:

1。)用仪器运行我的项目,让它在启动后立即搜索泄漏,没有。 2.)运行XML解析器一次,检查是否存在泄漏。没有了。 3.)再次运行XML Parser,现在突然出现[entryDict setObject:[tempString copy] forKey:kXMLDictDateKey];泄漏的行。

我几个小时以来一直在研究这些内存泄漏,我忘记了什么?如果你需要更多代码,请告诉我,虽然我认为我的问题在这些方面。

聚苯乙烯。我的检查显示在解析器(委托)调用之间调用“dealloc”方法,因此我认为解析器实际上已经加载了两次,而不仅仅是一次。

4 个答案:

答案 0 :(得分:3)

您致电:

tempString = [NSMutableString string];

实际上不会调用属性(包装器)和retain

你应该这样做:

self.tempString = [NSMutableString string];

否则,您只是将ivar直接设置为自动释放的对象。

你不仅在某个地方有泄漏,上面的代码会导致一些有趣的崩溃。

答案 1 :(得分:1)

代码中的另一个错误是:

[tempString appendString:[[XMLParser alloc]
    stripUnwantedStringChars:string]];

这会分配一个新的XMLParser,永远不会消除它。

答案 2 :(得分:1)

我正在试图弄清楚你在tempString的任务中最终做了些什么。如果你这样做:

self.tempString = [NSMutableString string];

然后你必须在dealloc中释放tempString。即使它是自动释放的,设置者也会保留它。

答案 3 :(得分:0)

首先,我认为这应该会崩溃,因为自动释放的可变字符串应该在从parserDidStartDocument返回后不久发布。它并不是一种令人担忧的问题,而且你还在说明财产的定义,并声明财产在未归属时保留。

然而,Leaks告诉你的是,字符串的副本已经泄露 - 泄漏显示了对象泄漏的分配位置,但这不是泄漏的原因。泄漏的原因是您没有的代码行应该稍后正确地释放该字符串。由于Leaks无法指向不存在的代码,因此它可以向您显示的是使对象无法正确释放的原因。

在这种情况下,我认为你缺少的是一个数组应该包含自动释放的对象 - 所以你想说:

[entryDict setObject:[[tempString copy] autorelease] forKey:kXMLDictDateKey];

因为Copy也保留了副本(就像alloc / init一样)。