2011-07-07 33 views
1

就在我以爲我已經得到了Objective-C的內存管理這個錯誤給我的印象來自無處的竅門......的NSXMLParser和「修改之後被釋放」錯誤

請考慮下面的代碼:

@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 

構建在initializedata對象似乎掀起了末日機器。如果我取消註釋,則消息消失。

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

我思念的東西從NSString構建NSData對象時?

感謝您的任何建議和問候 KC

回答

3

的dealloc應該做[super dealloc]釋放所有的實例變量:

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

,因爲它是在NSObject實際釋放該對象使用的內存dealloc。當您將條目設置爲零時,您正在寫入已經釋放的一塊內存。


一些其他意見:

看來我錯了,你是在-init做的工作。我會建議你有一個實際調用解析器的方法(調用它,比如說,-parse)。目前,您正在對一個無法完全初始化的對象執行相當複雜的操作。

而且,最好不要打電話給你的init方法-initialize:避免與+initialize具有可可特定的含義混淆。我把它叫做-initWithContent:

此外,您的實例變量被初始化爲零-init之前,讓線條狀

ivar = nil; 

init沒有意義的,你還需要釋放dealloc所有您的實例變量。

+0

你會看看那個!再見神祕記憶留言!感謝您的建議,我會牢記這些命名約定。 –

1

[super dealloc]應在結束時調用。 Plus分配您分配的對象。分配的對象可以通過發送消息nil來釋放,如entries = nil

ATB。

+1

'entries = nil'在任何情況下都不會釋放條目。 '自我。entries = nil'會,但最好不要在'-dealloc'發送消息給自己。 – JeremyP

+0

是我的壞。爲什麼你不想在dealloc中使用self,如果你有getter和setter的話? –

+0

因爲它可能調用子類中的重寫方法或觸發KVO通知。 – JeremyP

相關問題