问题
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.
回答1:
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];
回答2:
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.
回答3:
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
回答4:
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.
来源:https://stackoverflow.com/questions/6723470/weird-crash-if-i-try-to-release-cxmldocument