Pascal Kesseli
Pascal Kesseli

Reputation: 1670

NSXmlParser and "modified after being freed" error

Just when I thought I had gotten the hang of Objective-C's memory-management this error strikes me from nowhere...

Please consider the following code:

@implementation JglpNewsEntryParser


- (JglpNewsEntryParser *) initialize : (NSString *)content {
    self = [super init];
    if (self) {
        currentHeader = nil;
        currentText = nil;
        currentDate = nil;
        currentFullArticleUrl = nil;
        entries = [[NSMutableArray alloc] init];
        NSData *data = [content dataUsingEncoding: [NSString defaultCStringEncoding]];
        NSXMLParser *parser = [[[NSXMLParser alloc] initWithData:data] autorelease];
        [parser setDelegate: self];
        [parser parse];
    }
    return self;
}

- (void)parser: (NSXMLParser *)parser didStartElement: (NSString *)elementName namespaceURI: (NSString *)namespaceURI qualifiedName: (NSString *)qName attributes: (NSDictionary *)attributeDict {
    NSLog(@"Start!");
}

- (void)parser: (NSXMLParser *)parser didEndElement: (NSString *)elementName namespaceURI: (NSString *)namespaceURI qualifiedName: (NSString *)qName {
    NSLog(@"End!");
}

- (void)parser: (NSXMLParser *)parser foundCharacters: (NSString *)content {
    NSLog(@"Char!");
}

- (void)dealloc {
    [super dealloc];
    [entries release];
    entries = nil;
}

The class is used in my unit test in the following manner:

- (void) testConstruct {
    NSString *path = [[NSBundle bundleForClass:JglpNewsEntryParserTest.class] pathForResource: @"single-news-entry" ofType: @"html"];
    NSError *error = nil;
    NSString *data = [NSString stringWithContentsOfFile: path encoding: NSUTF8StringEncoding error: &error];
    JglpNewsEntryParser *parser = [[[JglpNewsEntryParser alloc] initialize: data] autorelease];
    STFail(@"");
}

After printing the "Start!", "End!" and "Char!" messages once, since the text XML contains only one entry, the test fails as it is supposed to at STFail. However, I do receive the following memory error message afterwards:

malloc: *** error for object 0xedf434: incorrect checksum for freed object - object was probably modified after being freed.
*** set a breakpoint in malloc_error_break to debug

Constructing the data object in initialize seems set off the doomsday machine. If I uncomment it, the message disappears.

        // ...
        /*NSData *data = [content dataUsingEncoding: [NSString defaultCStringEncoding]];
        NSXMLParser *parser = [[[NSXMLParser alloc] initWithData:data] autorelease];
        [parser setDelegate: self];
        [parser parse];*/
    }
    return self;
}

Am I missing something when constructing the NSData object from the NSString?

Thanks for any suggestions and best regards KC

Upvotes: 1

Views: 316

Answers (2)

JeremyP
JeremyP

Reputation: 86651

Dealloc should do [super dealloc] after releasing all the instance variables:

- (void)dealloc {
    [entries release];
    entries = nil;
    [super dealloc];
}

because it is dealloc in NSObject that actually frees the memory used by the object. When you set entries to nil, you are writing to a block of memory that has been freed already.


Some other comments:

It seems wrong to me that you are doing work in -init. I would recommend that you have a method (call it, say, -parse) that actually invokes the parser. At the moment you are performing quite complex ooperations on an object that isn't guranteed to be fully initialised.

Also, it's best not to call your init method -initialize: to avoid confusion with +initialize which has a specific meaning in Cocoa. I'd call it -initWithContent:

Also, your instance variables are initialised to nil before -init, so lines like

ivar = nil;

are pointless in init and you also need to release all your instance variables in dealloc.

Upvotes: 3

Praveen S
Praveen S

Reputation: 10393

The [super dealloc] should be called at the end. Plus release objects which you allocate. An allocated object can be released by sending a message nil to it like entries = nil.

ATB.

Upvotes: 1

Related Questions