Seltsam iPhone Speicherleck im XML-Parser
-
06-07-2019 - |
Frage
Aktualisieren : Ich habe das Code, aber das Problem weiterhin besteht ...
Hallo allerseits,
dies ist mein erster Beitrag hier - ich diesen Ort eine große Ressource für die Lösung viele meiner Fragen gefunden. Normalerweise versuche ich mein Bestes, alles auf eigene Faust zu beheben, aber dieses Mal habe ich wirklich keine Ahnung, was schief geht, so hoffe ich, jemand kann mir helfen.
Ich baue eine iPhone App, die ein paar XML-Dateien mit TouchXML analysiert. Ich habe eine Klasse XMLParser, die sich um das Herunterladen und Analysieren der Ergebnisse erfolgt. Ich erhalte Speicherlecks, wenn ich eine XML-Datei mehr als einmal analysiere mit der gleichen Instanz von XMLParser.
Hier ist eine der Parsing-Schnipsel (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, analysiere ich die xml kein Leck in Instrumenten auftaucht, das nächste Mal, wenn ich dies tun, ich habe eine Menge von Leckagen bekam (NSCFString / NSCFDictionary).
Instruments weist mich auf dieser Teil innerhalb CXMLNode.m , wenn ich in einem durchgesickerten Objekt graben:
theStringValue = [NSString stringWithUTF8String:(const char *)theXMLString];
if ( _node->type != CXMLTextKind )
xmlFree(theXMLString);
}
return(theStringValue);
Ich habe wirklich eine lange Zeit und mehrere Ansätze versucht, dieses Problem zu beheben, aber bisher ohne Erfolg, vielleicht bin ich etwas fehlt wesentlich?
Jede Hilfe sehr geschätzt wird, danke!
Lösung
Das Problem ist wahrscheinlich in dieser Zeile:
[self.mobil addObject:[product copy]];
für eine Kopie von product
Durch den Aufruf sind Sie eine neue NSMutableDictionary-Instanz mit einem Beibehaltungszähler von 1. Die mobil
Instanz erstellen, wird jedoch erhöhen den die Kopienzahl beibehalten, wenn Sie ihm die addObject:
Nachricht zu senden, so dass die Beibehaltungszähler von die Kopie ist jetzt 2. Im Allgemeinen ist es eine Aufgabe für den Umgang mit seinem eigenen Objektspeicher verantwortlich ist, so jedes Mal, wenn Nachricht setFoo:
oder addObject:
, können Sie einfach das Objekt direkt übergeben, auch wenn seine Autoreleased oder Sie planen, um sie zu lösen direkt nach der Anruf; es liegt in der Verantwortung des Empfängers das Objekt, das Sie vorbei zu behalten, wenn sie auf ihn zu halten brauchen.
Weil Sie nicht die Kopie zu jeder Variablen zugewiesen haben, haben Sie nicht einen Zeiger, den Sie die Kopie des Beibehaltungszähler können nun verringern, dass Sie nicht mehr daran interessiert, so dass selbst wenn mobil
gibt die Produktkopie an Irgendwann wird die Kopie nie das Objekt Original [product release]
für Schleife Meldungen am Ende der Zählung von 0. Ihrer product
Aussage behalten erreichen, nicht die Kopie, die Sie erstellt hat.
Stattdessen versuchen die folgenden und sehen, ob Instrumente glücklicher ist:
[self.mobil addObject:product];
Andere Tipps
In einfachen Worten, jedes Mal wenn Sie copy
verwenden zu können, müssen auch irgendwo release
/ autorelease
verwenden.
Und in diesem Fall, die noch einfache Antwort ist nicht copy
in erster Linie zu verwenden, da Sie nicht mit der Originalversion von product
etwas tun, nachdem Sie es kopiert haben.
Ich reparierte das Problem selbst. Es war irgendwie dumm, aber vielleicht könnte jemand über die gleiche Sache kommen, so werde ich es hier posten.
1) Ich änderbare Array einrichten als Instanzvariablen wie folgt hatte:
@interface XMLParser : NSObject {
// ...
NSMutableArray *mobil;
// ...
}
@property(nonatomic, retain) NSMutableArray *mobil;
@end
Jedesmal, wenn ich neue Daten wiederherstellen wollte innerhalb ich getan habe:
self.mobil = nil;
Was tat nicht, was ich tun wollte, so ist dies der bessere Ansatz:
[Self.mobil removeAllObjects];
2) Die dealloc Methode muss sein wie dies die Lecks zu reparieren (weil mobil als eine Eigenschaft definiert ist):
- (void) {dealloc
[Mobil release];
self.mobil = nil;
}
Puh, das eine Menge Arbeit gewesen, um herauszufinden - hoffen, dass es spart einige Zeit jemand anderes :-)