当我以为我已经掌握了Objective-C的内存管理时,这个错误让我无处可逃......
请考虑以下代码:
@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;
}
该类用于我的单元测试,方法如下:
- (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(@"");
}
打印“开始!”,“结束!”和“Char!”消息一次,因为文本XML只包含一个条目,测试失败,因为它应该在STFail
。但是,之后我收到以下内存错误消息:
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
在data
中构建initialize
对象似乎引发了世界末日机器。如果我取消注释,消息就会消失。
// ...
/*NSData *data = [content dataUsingEncoding: [NSString defaultCStringEncoding]];
NSXMLParser *parser = [[[NSXMLParser alloc] initWithData:data] autorelease];
[parser setDelegate: self];
[parser parse];*/
}
return self;
}
从NSData
构建NSString
对象时,我是否遗漏了某些内容?
感谢您的任何建议和问候 KC
答案 0 :(得分:3)
在发布所有实例变量后,Dealloc应该[super dealloc]
:
- (void)dealloc {
[entries release];
entries = nil;
[super dealloc];
}
因为dealloc
中的NSObject
实际上释放了对象使用的内存。当您将条目设置为nil时,您正在写入已经释放的内存块。
其他一些评论:
我在-init
开展工作似乎不对。我建议你有一个实际调用解析器的方法(称之为,例如,-parse)。目前,您正在对一个无法完全初始化的对象执行相当复杂的操作。
此外,最好不要调用init方法-initialize:
以避免与在Cocoa中具有特定含义的+initialize
混淆。我称之为-initWithContent:
此外,您的实例变量在-init
之前初始化为nil,所以像
ivar = nil;
<{1>}中的毫无意义,您还需要在init
中释放所有您的实例变量。
答案 1 :(得分:1)
最后应调用[super dealloc]
。再发布您分配的对象。可以通过向entries = nil
发送消息nil来释放已分配的对象。
ATB。