My favorites | Sign in
Project Home
READ-ONLY: This project has been archived. For more information see this post.
Search
for
  Advanced search   Search tips   Subscriptions
Issue 3: Problem releasing a CXMLDocument
2 people starred this issue and may be notified of changes. Back to list
Status:  Fixed
Owner:  jwight
Closed:  Apr 2008


 
Reported by sam.ste...@gmail.com, Mar 30, 2008
When releasing a CXMLDocument object, I get a lot of warnings about objects
being modified after they were free'd.  I've found the patch below resolves
this issue:

Index: CXMLNode_PrivateExtensions.m
===================================================================
--- CXMLNode_PrivateExtensions.m	(revision 32)
+++ CXMLNode_PrivateExtensions.m	(working copy)
@@ -42,7 +42,7 @@
 		return(NULL);
 	}
 
-CXMLNode *theNode = [[[theClass alloc] initWithLibXMLNode:inLibXMLNode]
autorelease];
+CXMLNode *theNode = [[theClass alloc] initWithLibXMLNode:inLibXMLNode];
 
 
 CXMLDocument *theXMLDocument = inLibXMLNode->doc->_private;

Apr 1, 2008
Project Member #1 jwight
Hey Sam, your patch actually causes all nodes to leak. I'm not going to accept the patch.

Could you please provide more information on how to reproduce the warnings?

Thanks.
Apr 1, 2008
#2 sam.ste...@gmail.com
Here is a snippit of code I'm using, it works fine using the NSXML* classes but
generates warnings about malloc checksums not matching using CXML classes:

		NSMutableURLRequest *theRequest = [NSMutableURLRequest requestWithURL:[NSURL
URLWithString:url] cachePolicy:NSURLRequestReloadIgnoringCacheData
timeoutInterval:30.0f];
		[theRequest setValue:USER_AGENT forHTTPHeaderField:@"User-Agent"];
		NSData *theResponseData;
		NSURLResponse *theResponse = NULL;
		NSError *theError = NULL;
		
		theResponseData = [NSURLConnection sendSynchronousRequest:theRequest
returningResponse:&theResponse error:&theError];
		id errmsg = nil;
		if(theResponseData) {
			CXMLDocument *d = [[CXMLDocument alloc] initWithData:theResponseData options:0
error:&errmsg];
			
			if(d && [[[d childAtIndex:0] name] isEqualToString:@"profile"]) {
				NSArray *arrayNodes = [[d childAtIndex:0] children];
				NSEnumerator *arrayMembers = [arrayNodes objectEnumerator];
				CXMLNode *arrayNode = nil;
				
				while ((arrayNode = [arrayMembers nextObject])) {
					if([arrayNode stringValue])
						[output setObject:[arrayNode stringValue] forKey:[arrayNode name]];
				}
			}
			[d release];
		}
Apr 1, 2008
Project Member #3 jwight
OK. Thanks. Looking into it now.
Apr 1, 2008
Project Member #4 jwight
Unfortunately STILL not reproducing it. Only tested on Mac OS X - not in the iPhone simulator. Is that where 
you're seeing it?

Also you might be aware you can replace most of your code with a single "nodesForXPath" call.
Apr 1, 2008
#5 sam.ste...@gmail.com
I'm using the iPhone simulator.  The code was originally written for the jailbroken
API which had a crippled version of the NSXML classes available (no XPaths), I
haven't had a chance to update it to use XPaths.  

The message output to the console is:
"malloc: *** error for object 0x1253d00: incorrect checksum for freed object - object
was probably modified after being freed.
*** set a breakpoint in malloc_error_break to debug"

I can email you a link to the full app's source if that will be more useful than the
snippet I pasted.
Apr 1, 2008
#6 sam.ste...@gmail.com
Ok, here's an easy way to reproduce the issue:

Create a new project in XCode using the Cocoa Touch Application template and paste
the class below into MyView.m.  Add the TouchXML files to your project, link against
libxml2, and launch the app in the simulator.  The console will display my profile
info, and then several seconds later the simulator and the app will crash.  The crash
does not occur if the nodes are not set to autorelease.  There's definitely something
strange going on with the node memory management.  Sometimes if you're lucky you'll
see the incorrect checksum message before the app crashes.

@implementation MyView
-(NSDictionary *)fetchProfile:(NSString *)username {
	NSMutableDictionary *output = [[[NSMutableDictionary alloc] init] autorelease];
	
	NSString *url = [NSString
stringWithFormat:@"http://ws.audioscrobbler.com/1.0/user/%@/profile.xml", (NSString
*)CFURLCreateStringByAddingPercentEscapes(NULL, (CFStringRef)username, NULL,NULL,
kCFStringEncodingUTF8)];
	NSMutableURLRequest *theRequest = [NSMutableURLRequest requestWithURL:[NSURL
URLWithString:url] cachePolicy:NSURLRequestReloadIgnoringCacheData
timeoutInterval:30.0f];
	NSData *theResponseData;
	NSURLResponse *theResponse = NULL;
	NSError *theError = NULL;
	
	theResponseData = [NSURLConnection sendSynchronousRequest:theRequest
returningResponse:&theResponse error:&theError];
	id errmsg = nil;
	if(theResponseData) {
		CXMLDocument *d = [[CXMLDocument alloc] initWithData:theResponseData options:0
error:&errmsg];
		
		if(d && [[[d childAtIndex:0] name] isEqualToString:@"profile"]) {
			NSArray *arrayNodes = [[d childAtIndex:0] children];
			NSEnumerator *arrayMembers = [arrayNodes objectEnumerator];
			CXMLNode *arrayNode = nil;
			
			while ((arrayNode = [arrayMembers nextObject])) {
				if([arrayNode stringValue])
					[output setObject:[arrayNode stringValue] forKey:[arrayNode name]];
			}
		}
		[d release];
	}
	
	return output;
}
-(id)initWithFrame:(CGRect)frame {
	self = [super initWithFrame: frame];
	
	NSDictionary *profile = [self fetchProfile:@"c99koder"];
	NSLog(@"%@", profile);
	return self;
}
@end

Apr 1, 2008
Project Member #7 jwight
That helped a lot. Able to re-produce now. Fix? That's a different question. :-)
Owner: jwight
Labels: TouchXML
Apr 1, 2008
Project Member #8 jwight
There's a potential fix in revision r39. Please try it out and get back to me. Thanks!
Apr 2, 2008
#9 sam.ste...@gmail.com
r39 seems to have resolved it! I've tested it both in the test case mentioned above,
and in the full application too.  Thanks!
Apr 8, 2008
Project Member #10 jwight
Awesome. Marking as fixed. thanks for reporting the issue and providing test data. VERY much appreciated.
Status: Fixed

Powered by Google Project Hosting