Reputation: 1670
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
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
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