2009-06-20 6 views
3

aktualisieren: bearbeiten ich den Code, aber das Problem weiterhin besteht ...Seltsam iPhone Speicherleck im XML-Parser

Hallo allerseits,
dies hier meinen ersten Beitrag ist - ich diesen Ort gefunden eine große Ressource für viele meiner Fragen lösen. Normalerweise versuche ich mein Bestes, um irgendetwas selbst zu reparieren, aber dieses Mal habe ich wirklich keine Ahnung, was schief läuft, also hoffe ich, dass mir jemand helfen kann.
Ich baue eine iPhone App, die ein paar XML-Dateien mit TouchXML analysiert. Ich habe eine Klasse XMLParser, die sich um das Herunterladen und Parsen der Ergebnisse kümmert. Ich erhalte Speicherlecks, wenn ich eine XML-Datei mehr als einmal mit der gleichen Instanz von XMLParse analysiere. Hier eine der Parsing-Schnipsel ist (nur der relevante Teil):

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]; 
     } 

    } 

Das erste Mal, ich analysieren die XML kein Leck in Instrumenten auftaucht, ich das nächste Mal so zu tun, habe ich eine Menge von Leckagen (NSCFString/NSCFDictionary).
Instruments weist mich auf diesen Teil innerhalb CXMLNode.m, wenn ich graben sich in einem durchgesickerten Objekt:

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

return(theStringValue); 

ich wirklich eine lange Zeit verbracht und versucht, diese mehrere Ansätze zu beheben, aber ohne Erfolg bisher Vielleicht fehlt mir etwas Wesentliches?

Jede Hilfe wird sehr geschätzt, danke!

Antwort

3

Das Problem ist wahrscheinlich in dieser Zeile:

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

für eine Kopie von product Durch den Aufruf sind Sie mit einer Beibehaltungszähler von 1. Die mobil Fall jedoch eine neue NSMutableDictionary Instanz erstellen, wird das Inkrementieren Kopie behalten Zählung, wenn Sie es senden Sie die Nachricht, so dass die Retain-Anzahl der Kopie ist jetzt 2. Allgemein gesagt, ein Objekt ist verantwortlich für die Handhabung seiner eigenen Objekt Speicher, so dass Sie jederzeit die Nachricht setFoo: oder addObject: übergeben können Objekt direkt, auch wenn es automatisch freigegeben wurde oder Sie planen, es direkt nach dem Anruf freizugeben; Es liegt in der Verantwortung des Empfängers, das übergebene Objekt zu behalten, wenn es daran festhalten muss.

Da Sie die Kopie keiner Variablen zugewiesen haben, verfügen Sie nicht über einen Zeiger, mit dem Sie die Anzahl der Exemplare verringern können, wenn Sie nicht mehr daran interessiert sind, selbst wenn mobil die Produktkopie freigibt Zu einem bestimmten Zeitpunkt wird die Kopie nie eine Retain-Zahl von 0 erreichen. Ihre [product release]-Anweisung am Ende der for-Schleife gibt das ursprüngliche Objekt product frei, nicht die Kopie, die Sie erstellt haben.

Stattdessen versuchen die folgenden und sehen, ob Instrumente ist glücklicher:

[self.mobil addObject:product]; 
+0

Vielen Dank - das ist dumm von mir war. Leider sind die Lecks noch vorhanden, aber jetzt in der Klasse CXMLNode.m in dieser Zeile: theStringValue = [NSString stringWithUTF8String: (const char *) theXMLString]; if (_node-> type! = CXMLTextKind) \t xmlFree (theXMLString); } Rückgabe (theStringValue); – Chris

+0

ah Entschuldigung, ich konnte die Formatierung nicht richtig bekommen ... – Chris

+0

Hmmm ... das sieht eher wie eine Warnung vor einem möglichen Leck aus, als einen garantierten Lauch. Nichtsdestotrotz bin ich durch die Quelle für CXMLNode in TouchXML geblättert und kann diese Zeile überhaupt nicht finden ... welche Version des Projekts hast du und in welcher Zeile ist es? Ich stelle fest, dass der Autor, Jonathan Wight, von der TouchCode Google-Benutzergruppe ziemlich gut darin ist, auf Posts zu reagieren, die Lecks haben: http://groups.google.com/group/touchcode-dev –

1

In einfachen Worten, jedes Mal copy verwenden zu können, müssen auch irgendwo release/autorelease verwenden.

Und in diesem Fall ist die noch einfachere Antwort, copy an erster Stelle zu verwenden, da Sie nichts mit der ursprünglichen Version von product tun, nachdem Sie es kopiert haben.

1

Ich habe das Problem selbst behoben.Es war irgendwie blöd, aber vielleicht könnte jemand das Gleiche finden, also werde ich es hier posten.

1) Ich hatte änderbaren Array als Instanzvariablen wie folgt aufgebaut:

@interface XMLParser : NSObject { 

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

Jedesmal, wenn ich neue Daten innerhalb Ich habe wiederherstellen wollte:
self.mobil = nil;
Welches was ich nicht machen wollte, so ist dies der bessere Ansatz:
[self.mobil removeAllObjects];

2) Die dealloc Verfahren hat so sein, um die Lecks zu beheben (weil mobil als eine Eigenschaft definiert ist):
- (void) {dealloc
[Mobil Release];
self.mobil = null;
}

Puh, das eine Menge Arbeit, um herauszufinden, war - Hoffnung spart es jemand anderes einige Zeit :-)