【问题标题】:Weird crash if I try to release CXMLDocument如果我尝试发布 CXMLDocument 会发生奇怪的崩溃
【发布时间】:2011-07-17 11:14:58
【问题描述】:

我正在使用 TouchXML 解析一些 XML,但我遇到了崩溃 -EXC_BAD_ACCESS。我通过反复试验发现,如果我不发布我的 CXMLDocument(我分配的),那么一切都很好。这是我的代码:

- (NSArray *)getLookUps {

    //Do some stuff and then...

    NSData *tempData = [NSURLConnection sendSynchronousRequest:request 
                                                 returningResponse:nil 
                                                             error:nil];



        CXMLDocument *xmlDoc = [[CXMLDocument alloc] initWithData:tempData options:0 error:nil];
        NSDictionary *mappings = [NSDictionary dictionaryWithObject:@"http://****/****" 
                                                             forKey:@"****"];

        NSLog(@"%@", [[NSString alloc] initWithData:tempData encoding:NSUTF8StringEncoding]);
        NSArray *orders = [[xmlDoc rootElement] nodesForXPath:@"//****:Unit" 
                                            namespaceMappings:mappings 
                                                        error:nil];

        NSMutableArray *units = [NSMutableArray arrayWithCapacity:200];

        for (CXMLElement *order in orders) {
            NSArray *nodes = [order children];
            NSMutableDictionary *dictionary = [NSMutableDictionary dictionaryWithCapacity:[nodes count]];

            for (CXMLElement *node in nodes) {
                [dictionary setObject:[node stringValue] forKey:[node name]];
            }
            [units addObject:dictionary];
        }

        //[xmlDoc release];
    return units;
}

请参阅第 2 行的最后一行,[xmlDoc release]。我已经对此发表了评论,因为如果我不这样做,它就会崩溃。我究竟做错了什么?谢谢。

【问题讨论】:

  • 在某些时候,您无法保留或过度发布某些内容。泄漏 CXMLDocument 只是隐藏了问题。你如何处理这个方法返回的数组?你能显示调用这个方法的代码吗?

标签: objective-c ios cocoa-touch touchxml


【解决方案1】:

您可能需要保留您的字典对象,否则当您释放解析器时它也会被释放。尝试将[units addObject:dictionary]; 更改为[units addObject:[dictionary retain]];

另一个想法是将您的 xmlDoc 指针设置为自动释放:

CXMLDocument *xmlDoc = [[[CXMLDocument alloc] initWithData:tempData options:0 error:nil] autorelease];

【讨论】:

  • 感谢您的回复。我将其更改为自动释放,并且不再崩溃。但是我不明白为什么当我明确释放它时它会崩溃......如果有其他需要它不应该保留它吗?我有很多其他类使用几乎完全相同的代码,它们不会自动释放,但不会崩溃。不管怎样,谢谢你的帮助/
  • 我相信arrayWithCapacitydictionaryWithCapacity 创建了自动释放的对象,因此当您发布xmlDoc 时它们可能会提前释放。
  • 对不起,如果这是一个菜鸟问题,但是 NSArray 或 NSDictionary 与 CXMLDocument 有什么关系?
  • 好吧,从你的问题来看,不清楚它是否真的是崩溃的确切点,但我认为当你尝试访问 Units Array 中的元素或 Units Array 中的 Dictionary 时它会崩溃?
  • 不,这是在 NSOperation 中运行的,有时在其中运行,它崩溃了,XCode 将我带到一个 TouchXML 类并指向它崩溃的行。
【解决方案2】:

已报告此错误,并在较新版本的库中标记为已修复。

http://code.google.com/p/touchcode/issues/detail?id=35

我还没有测试它是否真的修复了,该 URL 上的评论表明它不是。

在我看来,应该完全避免使用这个库。对于 iOS 应用,使用 libxml2 有几个原因:

  • 它已经过彻底的测试和尝试
  • 快速高效
  • 构建基于节点的 XML 表示可能会使编码变得更容易,但它会浪费内存,因为您总是将整个文档放在内存中。解析时您可能不止一次拥有它。相反,您应该设计您的代码以使用 libxml2 方法。一旦您开始解析大量文档,您就会同意。

【讨论】:

    【解决方案3】:

    我经常使用 TouchXML,而且(幸运的是?)我到现在都没有这个问题,但它只是发生了......

    我在这里发布了一个解决方案: Memory crash using [CXMLNode nodesForXPath] with namespace mappings

    【讨论】:

      【解决方案4】:

      我在 TouchXML 类“CXMLDocument”中观察到我们在“dealloc”方法中有以下处理。

      - (void)dealloc
      {
          // Fix for #35 http://code.google.com/p/touchcode/issues/detail?id=35 -- clear up the node objects first (inside a pool so I _know_ they're cleared) and then freeing the document
      
          @autoreleasepool {
      
              nodePool = NULL;
      
          }
          //
          xmlUnlinkNode(_node);
          xmlFreeDoc((xmlDocPtr)_node);
          _node = NULL;
      }
      

      我不确定我们为什么在“dealloc”中使用“autoreleasepool”。这是标准编码吗?如果我错了,请纠正我。

      【讨论】:

        猜你喜欢
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 2015-12-28
        • 2021-12-01
        • 1970-01-01
        • 2018-02-28
        • 1970-01-01
        相关资源
        最近更新 更多