Weird crash if I try to release CXMLDocument

2019-09-17 14:35发布

I am parsing some XML using TouchXML and I am getting a crash -EXC_BAD_ACCESS. What I found out through trial and error was that if I don't release my CXMLDocument (which I allocate), then everything is fine. Here's my code:

- (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;
}

See on the 2nd last line, [xmlDoc release]. I have commented that out, because it crashes if I don't. What am I doing wrong? Thanks.

4条回答
爱情/是我丢掉的垃圾
2楼-- · 2019-09-17 15:10

I used TouchXML quite often, and (fortunately?) I did not have this problem up to now, but it just happened ...

I posted a solution here: Memory crash using [CXMLNode nodesForXPath] with namespace mappings

查看更多
成全新的幸福
3楼-- · 2019-09-17 15:20

This bug was reported and is flagged as fixed in the newer versions of the library.

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

I haven't tested to see if it is actually fixed, a comment at that URL suggests that it isn't.

In my opinion, this library should be avoided altogether. For iOS apps, use libxml2 for several reasons:

  • It's tested and tried, through and through
  • It's fast and efficient
  • Building a node based representation of your XML might make it easier to code with, but it wastes memory as you always have the entire document in memory. You probably have it more than once while parsing. You should instead design your code to work with the libxml2 approach. You'll agree once you start parsing documents of substantial size.
查看更多
Root(大扎)
4楼-- · 2019-09-17 15:21

You probably need to retain your dictionary object otherwise it will also be released when you release the parser. Try changing [units addObject:dictionary]; to [units addObject:[dictionary retain]];.

Another idea is to set your xmlDoc pointer to autorelease:

CXMLDocument *xmlDoc = [[[CXMLDocument alloc] initWithData:tempData options:0 error:nil] autorelease];
查看更多
干净又极端
5楼-- · 2019-09-17 15:25

I observed in TouchXML Class "CXMLDocument" we have the following handling in "dealloc" method.

- (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;
}

I am not sure why we are using "autoreleasepool" in "dealloc". Is this is standard coding? Correct me if I am wrong.

查看更多
登录 后发表回答