在XML解析器奇怪iPhone内存泄漏

问题描述:

更新:我编辑的代码,但问题仍然存在...在XML解析器奇怪iPhone内存泄漏

大家好,
这这里是我的第一篇文章 - 我发现这个地方有很大的ressource为解决了我的许多问题。通常我会尽我所能来解决所有问题,但这次我真的不知道什么地方出了问题,所以我希望有人能帮助我。
我正在构建一个使用TouchXML分析几个xml文件的iPhone应用程序。我有一个XMLParser类,负责下载和解析结果。当我使用同一个XMLParser实例多次解析xml文件时,我得到内存泄漏。 这里是解析片段(只是相关部分)中的一个:

for(int counter = 0; counter < [item childCount]; counter++) { 
     CXMLNode *child = [item childAtIndex:counter]; 
     if([[child name] isEqualToString:@"PRODUCT"]) 
     { 
      NSMutableDictionary *product = [[NSMutableDictionary alloc] init]; 
      for(int j = 0; j < [child childCount]; j++) { 
       CXMLNode *grandchild = [child childAtIndex:j]; 
       if([[grandchild stringValue] length] > 1) { 
        NSString *trimmedString = [[grandchild stringValue] stringByTrimmingCharactersInSet:[NSCharacterSet whitespaceAndNewlineCharacterSet]]; 
        [product setObject:trimmedString forKey:[grandchild name]]; 
       } 
      } 

      // Add product to current category array 
      switch (categoryId) { 
       case 0: 
        [self.mobil addObject: product]; 
        break; 
       case 1: 
        [self.allgemein addObject: product]; 
        break; 
       case 2: 
        [self.besitzeIch addObject: product]; 
        break; 
       case 3: 
        [self.willIch addObject: product]; 
        break; 
       default: 
        break; 
      } 
      [product release]; 
     } 

    } 

第一次,我解析XML无泄漏仪表显示出来,下一次我这样做,我得到了很多的泄漏(NSCFString/NSCFDictionary)。
仪器指向我内CXMLNode.m,当我挖到泄漏的对象这一部分:

theStringValue = [NSString stringWithUTF8String:(const char *)theXMLString]; 
if (_node->type != CXMLTextKind) 
    xmlFree(theXMLString); 
} 

return(theStringValue); 

我真的花了很长时间,并试图多种方法来解决这个问题,但都无济于事到目前为止,也许我错过了一些重要的东西?

任何帮助,高度赞赏,谢谢!

的问题很可能在这一行:

[self.mobil addObject:[product copy]]; 

通过调用为product副本你用1 mobil实例保留计数创建一个新的NSMutableDictionary实例,但是,将递增当你发送addObject:消息时,副本的保留计数,所以副本的保留计数现在是2.一般来说,一个对象负责处理它自己的对象内存,所以任何时候你发送消息setFoo:addObject:,你可以通过直接对象,即使它是自动发布的,或者你打算在调用之后立即释放它;接收方有责任在需要保留的情况下保留传递的对象。

因为您没有将副本分配给任何变量,所以即使您已不再对此副本感兴趣,您也没有可用于减少副本保留计数的指针,因此即使mobil发布产品副本在某些时候,副本永远不会达到保留计数0.您在for循环结束时的[product release]语句会释放原始对象product,而不是您创建的副本。

相反,请尝试以下,看看仪器是快乐:

[self.mobil addObject:product]; 
+0

非常感谢你 - 那是我傻的。不幸的是,泄漏仍然存在,但现在在此行的CXMLNode.m类中: theStringValue = [NSString stringWithUTF8String :(const char *)theXMLString]; if(_node-> type!= CXMLTextKind) \t xmlFree(theXMLString); } return(theStringValue); – Chris 2009-06-20 11:49:24

简单来说,每次使用copy时间,你也可以选择使用release/autorelease地方。

而在这种情况下,更简单的答案是首先不要使用copy,因为您在复制之后没有对原始版本product做任何处理。

我自己解决了这个问题。这有点愚蠢,但也许有人会遇到同样的事情,所以我会在这里发布。

1)我有可变数组设置为实例变量是这样的:

@interface XMLParser : NSObject { 

// ... 
NSMutableArray *mobil; 
// ... 
} 
@property(nonatomic, retain) NSMutableArray *mobil; 
@end 

每次我想要恢复新的数据里面我做:
self.mobil =零;
哪个不是我想要做的,所以这是更好的方法:
[self.mobil removeAllObjects];

2)dealloc方法必须是这样来解决泄漏(因为美孚被定义为属性):
- (无效)的dealloc {
[美孚释放];
self.mobil = nil;
}

呼,已经做了大量的工作,找出 - 希望这样可以节省别人的一段时间:-)