更新:我编辑了代码,但问题仍然存在......

大家好,
这是我在这里的第一篇文章 - 我发现这个地方是一个很好的资源来解决我的许多问题。通常我会尽我所能来解决自己的问题,但这次我真的不知道出了什么问题,所以我希望有人可以帮助我。
我正在构建一个iPhone应用程序,使用TouchXML解析几个xml文件。我有一个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 的副本,您将创建一个新的NSMutableDictionary实例,其保留计数为1.但 mobil 实例将增加副本的保留当你发送 addObject:消息时计算,所以拷贝的保留计数现在是2.一般来说,一个对象负责处理它自己的对象内存,所以每当你发送消息 setFoo: addObject:,你可以直接传递对象,即使它是自动释放的,或者你打算在通话后立即释放它;接收者有责任保留你传递的物体,如果它需要保持它。

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

相反,请尝试以下操作,看看乐器是否更快乐:

[self.mobil addObject:product];

其他提示

简单来说,每次使用 copy 时,您还必须在某处使用 release / autorelease

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

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

1)我将可变数组设置为实例变量,如下所示:

@interface XMLParser : NSObject {

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

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

2)dealloc方法必须像这样来修复泄漏(因为mobil被定义为属性):
     - (void)dealloc {
      [美孚释放];
      self.mobil = nil;
  }

哇,这已经做了很多工作 - 希望能节省一些时间:-)

许可以下: CC-BY-SA归因
不隶属于 StackOverflow
scroll top