zzycami / touchcode

Automatically exported from code.google.com/p/touchcode
0 stars 0 forks source link

Problem releasing a CXMLDocument #3

Closed GoogleCodeExporter closed 8 years ago

GoogleCodeExporter commented 8 years ago
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;

Original issue reported on code.google.com by sam.ste...@gmail.com on 31 Mar 2008 at 2:53

GoogleCodeExporter commented 8 years ago
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.

Original comment by jwight on 1 Apr 2008 at 3:31

GoogleCodeExporter commented 8 years ago
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];
        }

Original comment by sam.ste...@gmail.com on 1 Apr 2008 at 4:53

GoogleCodeExporter commented 8 years ago
OK. Thanks. Looking into it now.

Original comment by jwight on 1 Apr 2008 at 8:18

GoogleCodeExporter commented 8 years ago
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.

Original comment by jwight on 1 Apr 2008 at 8:27

GoogleCodeExporter commented 8 years ago
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.

Original comment by sam.ste...@gmail.com on 1 Apr 2008 at 10:03

GoogleCodeExporter commented 8 years ago
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

Original comment by sam.ste...@gmail.com on 2 Apr 2008 at 1:10

GoogleCodeExporter commented 8 years ago
That helped a lot. Able to re-produce now. Fix? That's a different question. :-)

Original comment by jwight on 2 Apr 2008 at 1:41

GoogleCodeExporter commented 8 years ago
There's a potential fix in revision r39. Please try it out and get back to me. 
Thanks!

Original comment by jwight on 2 Apr 2008 at 1:56

GoogleCodeExporter commented 8 years ago
r39 seems to have resolved it! I've tested it both in the test case mentioned 
above,
and in the full application too.  Thanks!

Original comment by sam.ste...@gmail.com on 3 Apr 2008 at 2:37

GoogleCodeExporter commented 8 years ago
Awesome. Marking as fixed. thanks for reporting the issue and providing test 
data. VERY much appreciated.

Original comment by jwight on 8 Apr 2008 at 9:58