如果我尝试发布CXMLDocument,则会发生奇怪的崩溃

时间:2011-07-17 11:14:58

标签: objective-c ios cocoa-touch touchxml

我正在使用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;
}

见最后一行,[xmlDoc release]。我已经评论过了,因为如果我不这样做会崩溃。我究竟做错了什么?感谢。

4 个答案:

答案 0 :(得分:1)

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

另一个想法是将xmlDoc指针设置为autorelease:

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

答案 1 :(得分:1)

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

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

我还没有测试过它是否确实已修复,该网址上的评论表明它不是。

在我看来,应该完全避免使用这个库。对于iOS应用程序,请使用libxml2,原因如下:

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

答案 2 :(得分:0)

我经常使用TouchXML,并且(幸运的是?)到目前为止我没有遇到这个问题,但它刚刚发生......

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

答案 3 :(得分:0)

我在TouchXML Class“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”。这是标准编码吗?如果我错了,请纠正我。