【问题标题】:Memory leak in XML ParserXML 解析器中的内存泄漏
【发布时间】:2011-01-11 07:19:12
【问题描述】:

我使用 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”方法,因此我认为解析器实际上被加载了两次,而不仅仅是一次。

【问题讨论】:

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


    【解决方案1】:

    您的电话:

    tempString = [NSMutableString string];
    

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

    你应该这样做:

    self.tempString = [NSMutableString string];
    

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

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

    【讨论】:

    • 非常感谢,这正是我所缺少的。现在它就像一个魅力:)
    【解决方案2】:

    您代码中的另一个错误是:

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

    这会分配一个新的XMLParser 并且永远不会摆脱它。

    【讨论】:

    • 是的,你是对的,我忘了在描述中写 XMLParser 是一个单例。因此,这不会创建 XMLParser 的新实例,而只是返回前一个实例。
    • 更好的方法是遵循 Apple 的风格并使用 sharedInstance 类方法。与alloc 混在一起创建一个单例是邪恶的,而且真的很糟糕。
    【解决方案3】:

    我试图弄清楚你在分配给 tempString 时最终做了什么。如果你这样做:

    self.tempString = [NSMutableString string];
    

    那么你必须在 dealloc 中释放 tempString。即使它被自动释放,setter 也会保留它。

    【讨论】:

      【解决方案4】:

      首先,我想这实际上应该崩溃,因为自动释放的可变字符串应该在您从 parserDidStartDocument 返回后不久释放。这并不令人担忧,而且您还声称该财产在没有保留时被保留,从而在您的财产定义中撒谎。

      但是,Leaks 告诉您的是字符串的副本已被泄露 - Leaks 向您显示了泄漏对象的分配位置,但这不是泄漏的原因。泄漏的原因是您没有应该稍后正确释放该字符串的代码行。由于 Leaks 无法指向不存在的代码,因此它只能向您显示导致对象未正确释放的原因。

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

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

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

      【讨论】:

      • 非常感谢您的快速回答。将 tempString 附加到 autorelease 的做法是从 Apple 在“XML Performance”项目中的示例代码中复制而来的。我已经添加了你建议的自动释放,但我仍然得到泄漏。为什么 tempString 没有正确释放对我来说是个谜(我怀疑这是问题所在?)。我还确保发布了“entryDict”,确实如此,所以我认为问题确实出在 tempString 之内。您还有其他想法可能导致泄漏吗?非常感谢您的努力!
      • 什么发布entryDict?如果那没有被释放,那么我可以看到它会说里面的元素正在泄漏。
      猜你喜欢
      • 1970-01-01
      • 2011-10-18
      • 2010-11-04
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2015-01-03
      • 1970-01-01
      • 1970-01-01
      相关资源
      最近更新 更多