2010-01-12 63 views
3

我正在使用XMLParser解析一些XML數據,它使用NSMutableString * resultString來存儲標記字符。在每個( - parser:didStarElement ...)方法中,我分配並初始化resultString-ivar。內存泄漏NSMutableString appendString

- (void)parser: (NSXMLParser *)parser didStartElement: (NSString *)elementName namespaceURI: (NSString *)namespaceURI qualifiedName: (NSString *)qName attributes: (NSDictionary *)attributeDict { 
// Alot of if-statements to sort subtags 
// /.../ 
    resultString = [[NSMutableString alloc] init]; 
    recordResults = YES; 
} 

將字符串添加到解析器中:foundCharacters-method。我在某處讀取自動釋放對象,比如appendString中的字符串可能導致內存泄漏的圖像。所以我加了一個本地autorelease池,以確保它得到倒掉馬上(的行爲沒有改變,雖然):

- (void)parser:(NSXMLParser *)parser foundCharacters:(NSString *)string { 
NSAutoreleasePool *pool = [[NSAutoreleasePool alloc] init]; 
if(recordResults) { 
    [resultString appendString: string]; 
} 
[pool drain]; 
} 

在解析器:didEndElement ......我終於釋放和無出resultsString:

-(void)parser:(NSXMLParser *)parser didEndElement:(NSString *)elementName namespaceURI:(NSString *)namespaceURI qualifiedName:(NSString *)qName { 

    // Alot of if statements to handle differnt tags 
    // each of which has the structure of the last else-statement 
    // In other words, I am pretty sure I've covered every possible 
    // case to prevent the resultString from 
    // not getting released and niled out 
    if(...) { 
      ... 
} 
    else if(...) { 
      ... 
    } 
else { 
    if(resultString != nil) { 
     [dataDict setObject: resultString forKey: elementName]; 
     [resultString release]; 
     resultString = nil; 
    } 
} 

儀器泄漏工具標記解析器:foundCharacter方法作爲內存泄漏的來源,所以我想知道這是否是由appendString引起的。或者如果你能在這段代碼中找到一些出錯的東西。 這是一個相當渴望內存的應用程序,解析iPhone上的相當多的,有時是中等大小的XML文件,所以我的問題是如何找到解決辦法,如果在這種情況下NSMutableString appendString不適合...

在此先感謝!

回答

3

如果結束標記丟失,您將有內存泄漏。最好在parserDidStartDocument中有任何分配:並且在parserDidEndDocument:中解除分配,因爲這些保證是成對的。而不是在didStartElement中分配resultString,您只需在那裏截斷它。

+0

我不確定parserDidEndDocument是否在解析錯誤時被調用,但這應該很容易測試。 – ergosys 2010-01-13 00:29:23

+0

好點!應該做一些性能改進,對,因爲我不必爲每個標記分配和初始化NSMutableString? 並截斷你只是建議設置[resultString setString:@「」]? – jollyCocoa 2010-01-13 06:48:00

+0

我試過你的這個解決方案。它似乎解決了這個問題。非常感謝! 我非常幸運能夠使用XML來處理所有關閉標記。但是,如果沒有,我想我可以實現解析器:parseErrorOccured或處理這些... – jollyCocoa 2010-01-13 08:09:10

0

我不認爲你可以知道appendString是否使用autorelease或不是,因爲該方法改變它的對象而不是返回一個新的對象。換句話說,因爲它自身在變化,所以你不需要爲它的內存管理負責。您也不擁有string,因此您不必釋放或自動釋放它。

檢查了這一點:http://developer.apple.com/mac/library/documentation/cocoa/Conceptual/MemoryMgmt/Articles/mmRules.html#//apple_ref/doc/uid/20000994-BAJHFBGH

這可能會澄清的事情,但隨着自動釋放了關鍵的是,「新」的對象比分配/初始化areautoreleased以外的東西回來。在這種情況下,appendString不會返回新對象,並且可以簡單地保留字符串,將其傳遞給解析器回調,稍後由調用者釋放,所以誰知道是否自動釋放。

當你需要自動釋放某些東西的時候,是當你有一個使用alloc/new/copy的函數/方法,然後返回該對象時,函數本身無法將它釋放。

+0

我同意我也可以省略autorelease池。我在這裏得到了一個關於stackoverflow的提示,雖然我不明白爲什麼它應該有所幫助,但我試了一下。我試圖在第一篇文章中提到,但顯然還不夠清楚。 – jollyCocoa 2010-01-13 06:45:17

0

自動釋放緩衝池沒有任何作用,因爲您不會自動釋放任何對象 - 您正在將可變字符串分配到一個位置,並將其釋放到另一個位置。 「appendString」對MutableString的保留計數沒有任何作用。

至於泄漏,這裏是處理 - 泄漏告訴你,內存泄漏是分配。所以這意味着在分配內存的部分中一切正常 - 不好的是,在其他地方,保留在該方法中的內存應該被釋放,但事實並非如此。

因此,在某些時候,似乎你從dataDict中取出resultString放置它,保留它並且不釋放它(在我看來,像釋放它一樣在解析過程中可以,所以不會是罪魁禍首)。要驗證這是如此,更改插入的字符串是::

[dataDict setObject:[[resultString copy] autorelease] forKey: elementName]; 

並泄漏應該告訴你泄漏是在那裏。爲了幫助追蹤泄漏,無論何時從dataDict中提取一個字符串,您都可以[複製]它,然後您將更接近泄漏字符串的確切代碼。

基本上泄漏就像一個有人死亡的神祕書的開幕。你可以找出兇手是誰 - 或者在泄漏情況下,誰應該殺人,但沒有解決。

+0

是的,你是對的。然而。它也沒有真正傷害,我仍然有泄漏,所以我仍然困惑。 – jollyCocoa 2010-01-13 06:46:34

+0

我添加了一個關於哪些泄漏事實真實地告訴我我的回覆的消息,對不起,我沒有在那天晚上了解更多的細節,但當時我太急了。 – 2010-01-14 00:33:23