【问题标题】:Memory leak issue during xml parsing?xml解析期间的内存泄漏问题?
【发布时间】:2012-03-19 07:29:39
【问题描述】:

我遇到了奇怪的内存泄漏问题,

现在我的代码是,

-(NSMutableDictionary *)getParsedWallpaperData{
NSMutableDictionary *dataDictionary = [NSMutableDictionary dictionary];

NSData *xmlData = [NSData dataWithContentsOfFile:[[NSBundle mainBundle] pathForResource:@"Wallpaper" ofType:@"xml"]];
TBXML *tbXml = [[TBXML alloc] initWithXMLData:xmlData error:nil];

//TBXML *tbXml = [[TBXML tbxmlWithXMLData:xmlData error:nil] autorelease];

@synchronized(self){
    TBXMLElement *rootXMLElement = tbXml.rootXMLElement;

    if(rootXMLElement)
    {
        TBXMLElement *paging = [TBXML childElementNamed:kPaging parentElement:rootXMLElement];
        NSMutableDictionary *pagingData = [[NSMutableDictionary alloc] init];
        if(paging){
            TBXMLElement *totalPages = [TBXML childElementNamed:kTotalPages parentElement:paging];
            NSString *totalPagesString = [TBXML textForElement:totalPages];
            [pagingData setObject:totalPagesString forKey:@"TotalPages"];

            TBXMLElement *currentPage = [TBXML childElementNamed:kCurrentPage parentElement:paging];
            NSString *currentPageString = [TBXML textForElement:currentPage];
            [pagingData setObject:currentPageString forKey:@"CurrentPage"];

            TBXMLElement *prevPage = [TBXML childElementNamed:kPerviousPage parentElement:paging];
            NSString *prevPageString = [TBXML textForElement:prevPage];
            [pagingData setObject:prevPageString forKey:@"PreviousPage"];

            TBXMLElement *nextPage = [TBXML childElementNamed:kNextPage parentElement:paging];
            NSString *nextPageString = [TBXML textForElement:nextPage];
            [pagingData setObject:nextPageString forKey:@"NextPage"];
        }
        [dataDictionary setObject:pagingData forKey:@"PagingInfo"];
        [pagingData release];
        pagingData = nil;

        TBXMLElement *totalItems = [TBXML childElementNamed:kTotalItems parentElement:rootXMLElement];
        NSString *totalItemsString = [TBXML textForElement:totalItems];
        [dataDictionary setObject:totalItemsString forKey:@"TotalItems"];

        NSMutableArray *itemArray = [[NSMutableArray alloc] initWithCapacity:[totalItemsString intValue]]; 

        TBXMLElement *items = [TBXML childElementNamed:kItems parentElement:rootXMLElement];
        if(items){
            TBXMLElement *item = [TBXML childElementNamed:kItem parentElement:items];
            while (item) {
                NSMutableDictionary *itemInfoDict = [[NSMutableDictionary alloc] init];
                TBXMLElement *title = [TBXML childElementNamed:kTitle parentElement:item];
                NSString *titleString = [TBXML textForElement:title];
                [itemInfoDict setObject:titleString forKey:@"Title"];

                TBXMLElement *image1 = [TBXML childElementNamed:kImage1 parentElement:item];
                NSString *image1String = [TBXML textForElement:image1];
                [itemInfoDict setObject:image1String forKey:@"Image1"];

                TBXMLElement *image2 = [TBXML childElementNamed:kImage2 parentElement:item];
                NSString *image2String = [TBXML textForElement:image2];
                [itemInfoDict setObject:image2String forKey:@"Image2"];

                TBXMLElement *image3 = [TBXML childElementNamed:kImage3 parentElement:item];
                NSString *image3String = [TBXML textForElement:image3];
                [itemInfoDict setObject:image3String forKey:@"Image3"];

                TBXMLElement *thumbnail = [TBXML childElementNamed:kThumbnail parentElement:item];
                NSString *thumbnailString = [TBXML textForElement:thumbnail];
                [itemInfoDict setObject:thumbnailString forKey:@"Thumbnail"];

                [itemArray addObject:itemInfoDict];
                [itemInfoDict release];
                itemInfoDict = nil;
                item = item -> nextSibling;
            }
        }
        [dataDictionary setObject:itemArray forKey:@"ImagesInfo"];
        [itemArray release];
        itemArray = nil;
    }
}

[tbXml release];
tbXml = nil; 
return dataDictionary;
 }

我发现只有内存泄漏 TBXML *tbXml = [[TBXML alloc] initWithXMLData:xmlData error:nil];在这条线上,即使我手动释放 tbXml 对象,

请告诉我这发生了什么?

谢谢,

【问题讨论】:

  • 您是否检查过它是否是 TBXML 库中的泄漏?
  • @freespace,我认为 TBXML 库中可能存在泄漏,因为当我使用分析器调试代码时,它在给定的代码中没有给我任何问题....但它显示了很多问题在 TBXML 库中... :(
  • 然后 (a) 向 TBXML 提交错误报告或 (b) 停止使用 TBXML 或 (c) 停止使用 XML。我推荐选项(c)。
  • 我同意@freespace 的选项c。如果你的包中的文件是 XML,那么用 json 文件替换它会使其更小,更容易使用。
  • @freespace 也错过了选项 a1) 修复 TBXML 中显示的错误。

标签: iphone objective-c ios ipad memory-leaks


【解决方案1】:

好吧,如果它是显示为泄漏的根元素,我想知道是否有像 childElementNamed 这样的访问器之一导致它(通过返回类似于 NSString 但实际上也存储了优化指针的东西到根元素)。可以看看childElementNamed的实现吗?更改代码以确保它不是这样的相对快速的方法是使用[NSString stringWithFormat:@"%@", [TBXML textForElement:fooTitle]] 调用将要存储在dataDictionary 中的任何NSString 结果包装起来。

此外,如果 TBXML 正在创建大量自动释放对象,您可以将此函数包装在 @nsautoreleasepool 宏中。

作为最后的建议,如果可以的话,您应该查看 ARC(即,如果您要部署到 iOS 4+)。

【讨论】:

  • 我实际上开始在 ARC 环境中编写代码,但我的客户改变了要求,他说我想在应用程序中为用户 paly cocos2d 游戏提供便利。而且该游戏代码与 ARC 不兼容,因此我选择非 ARC 应用程序... :(
  • 我在 TBXML *tbXml = [[TBXML alloc] initWithXMLData:xmlData error:nil] 上的仪器中有 100% 泄漏;这一行。
  • 是的——但这并不意味着问题出在 TBXML 中。某些东西正在引用该行上分配的内存;所以问题出在其他地方。
  • 我不这么认为,泄漏来自其他地方,因为如果泄漏来自其他地方,那么我在 Instrument 中获得了该对象的引用计数器......但它没有发生...... . 分析器也给出了产生泄漏的那一行....当我开始使用分析器分析我的代码时...它在我的代码中没有显示任何问题...但是是的,它在 TBXML 库中给出了许多缺陷。
  • 那时我们可能不得不同意不同意。 TBXML 中很可能存在泄漏,但具体而言,您没有得到保留此 TBXML 对象的内存。它不能在自身内部泄漏。转到分配/释放链。该对象的持有者(已泄漏)可能不会被识别为泄漏本身,因为它不是泄漏;它被有效引用。
【解决方案2】:

在函数顶部添加这一行:

NSAutoreleasePool *Pool=[[NSAutoreleasePool alloc]init];

并在函数底部的“return”语句之前添加这一行:

[Pool drain];

希望这会对你有所帮助。

【讨论】:

  • 更换[泳池排水管];到[池释放];行。
  • 实际上,您的 xmlData 占用了您应用程序的大部分内存,可能它有很多以 MB 为单位的数据。要解决此问题,请尝试分配 xmlData 并在完成该对象后立即释放该对象以适应 TBxml。
猜你喜欢
  • 2011-10-18
  • 1970-01-01
  • 2011-01-11
  • 2015-01-03
  • 1970-01-01
  • 2012-08-19
  • 1970-01-01
  • 2010-12-11
  • 1970-01-01
相关资源
最近更新 更多