2009-06-20 64 views
3

更新:我編輯的代碼,但問題仍然存在...在XML解析器奇怪iPhone內存泄漏

大家好,
這這裏是我的第一篇文章 - 我發現這個地方有很大的ressource爲解決了我的許多問題。通常我會盡我所能來解決所有問題,但這次我真的不知道什麼地方出了問題,所以我希望有人能幫助我。
我正在構建一個使用TouchXML分析幾個xml文件的iPhone應用程序。我有一個XMLParser類,負責下載和解析結果。當我使用同一個XMLParser實例多次解析xml文件時,我得到內存泄漏。 這裏是解析片段(只是相關部分)中的一個:

for(int counter = 0; counter < [item childCount]; counter++) { 
     CXMLNode *child = [item childAtIndex:counter]; 
     if([[child name] isEqualToString:@"PRODUCT"]) 
     { 
      NSMutableDictionary *product = [[NSMutableDictionary alloc] init]; 
      for(int j = 0; j < [child childCount]; j++) { 
       CXMLNode *grandchild = [child childAtIndex:j]; 
       if([[grandchild stringValue] length] > 1) { 
        NSString *trimmedString = [[grandchild stringValue] stringByTrimmingCharactersInSet:[NSCharacterSet whitespaceAndNewlineCharacterSet]]; 
        [product setObject:trimmedString forKey:[grandchild name]]; 
       } 
      } 

      // Add product to current category array 
      switch (categoryId) { 
       case 0: 
        [self.mobil addObject: product]; 
        break; 
       case 1: 
        [self.allgemein addObject: product]; 
        break; 
       case 2: 
        [self.besitzeIch addObject: product]; 
        break; 
       case 3: 
        [self.willIch addObject: product]; 
        break; 
       default: 
        break; 
      } 
      [product release]; 
     } 

    } 

第一次,我解析XML無泄漏儀表顯示出來,下一次我這樣做,我得到了很多的泄漏(NSCFString/NSCFDictionary)。
儀器指向我內CXMLNode.m,當我挖到泄漏的對象這一部分:

theStringValue = [NSString stringWithUTF8String:(const char *)theXMLString]; 
if (_node->type != CXMLTextKind) 
    xmlFree(theXMLString); 
} 

return(theStringValue); 

我真的花了很長時間,並試圖多種方法來解決這個問題,但都無濟於事到目前爲止,也許我錯過了一些重要的東西?

任何幫助,高度讚賞,謝謝!

回答

3

的問題很可能在這一行:

[self.mobil addObject:[product copy]]; 

通過調用爲product副本你用1 mobil實例保留計數創建一個新的NSMutableDictionary實例,但是,將遞增當你發送addObject:消息時,副本的保留計數,所以副本的保留計數現在是2.一般來說,一個對象負責處理它自己的對象內存,所以任何時候你發送消息setFoo:addObject:,你可以通過直接對象,即使它是自動發佈的,或者你打算在調用之後立即釋放它;接收方有責任在需要保留的情況下保留傳遞的對象。

因爲您沒有將副本分配給任何變量,所以即使您已不再對此副本感興趣,您也沒有可用於減少副本保留計數的指針,因此即使mobil發佈產品副本在某些時候,副本永遠不會達到保留計數0.您在for循環結束時的[product release]語句會釋放原始對象product,而不是您創建的副本。

相反,請嘗試以下,看看儀器是快樂:

[self.mobil addObject:product]; 
+0

非常感謝你 - 那是我傻的。不幸的是,泄漏仍然存在,但現在在此行的CXMLNode.m類中: theStringValue = [NSString stringWithUTF8String :(const char *)theXMLString]; if(_node-> type!= CXMLTextKind) \t xmlFree(theXMLString); } return(theStringValue); – Chris 2009-06-20 11:49:24

1

簡單來說,每次使用copy時間,你也可以選擇使用release/autorelease地方。

而在這種情況下,更簡單的答案是首先不要使用copy,因爲您在複製之後沒有對原始版本product做任何處理。

1

我自己解決了這個問題。這有點愚蠢,但也許有人會遇到同樣的事情,所以我會在這裏發佈。

1)我有可變數組設置爲實例變量是這樣的:

@interface XMLParser : NSObject { 

// ... 
NSMutableArray *mobil; 
// ... 
} 
@property(nonatomic, retain) NSMutableArray *mobil; 
@end 

每次我想要恢復新的數據裏面我做:
self.mobil =零;
哪個不是我想要做的,所以這是更好的方法:
[self.mobil removeAllObjects];

2)dealloc方法必須是這樣來解決泄漏(因爲美孚被定義爲屬性):
- (無效)的dealloc {
[美孚釋放];
self.mobil = nil;
}

呼,已經做了大量的工作,找出 - 希望這樣可以節省別人的一段時間:-)