14 Stimmen

Warum ist Autorelease für iPhone-Anwendungen besonders gefährlich/teuer?

Ich suche nach einer Primärquelle (oder einer wirklich guten Erklärung), die die Behauptung stützt, dass die Verwendung von autorelease gefährlich oder übermäßig teuer ist, wenn man Software für das iPhone schreibt.

Mehrere Entwickler stellen diese Behauptung auf, und ich habe sogar gehört, dass Apple dies nicht empfiehlt, aber ich habe keine konkreten Quellen finden können, die dies bestätigen.

SO Referenzen:
autorelease-iphone
Warum entsteht dadurch ein Speicherleck (iPhone)?

Anmerkung: Aus konzeptioneller Sicht kann ich feststellen, dass autorelease ist etwas teurer als ein einfacher Aufruf von release aber ich glaube nicht, dass diese geringe Strafe ausreicht, um Apple davon abzuraten.

Was ist die wahre Geschichte?

11voto

TofuBeer Punkte 59410

(Sie können Ihre eigene Antwort nicht akzeptieren?)

Nun, nach all dem ist es mir gelungen, einen Hinweis von Apple Developer zu finden, der als Randnotiz am Ende der Seite hinzugefügt wurde:

iPhone OS Hinweis: Da auf dem iPhone OS eine Anwendung in einem eher speicherbegrenzten Umgebung ausgeführt wird, ist die Verwendung von Autorelease-Pools wird in Methoden oder Codeblöcken (z.B. Codeblöcken (zum Beispiel Schleifen), in denen ein Anwendung viele Objekte erzeugt. Stattdessen sollten Sie explizit freigeben Objekte freigeben, wann immer dies möglich ist.

Dies legt jedoch nahe, die automatische Freigabe mit Bedacht einzusetzen und sie nicht ganz zu vermeiden.

(und nun zu meinem Kommentar)

Es klingt so, als ob die Instandhaltung des Pools mit einem gewissen Aufwand verbunden ist. Ich lese dieser Artikel was dazu führen würde, dass ich die automatische Freigabe so weit wie möglich vermeiden würde, weil ich es vorziehe, dass die Dinge konsistent sind. Wenn ein Teil des Speichers unter automatischer Freigabe steht und ein anderer Speicher vollständig manuell verwaltet wird, kann das etwas verwirrend sein.

9voto

Es geht nicht um die Frage, ob man die automatische Freigabe verwenden soll oder nicht, denn in manchen Fällen ist die automatische Freigabe die einzige Möglichkeit, um weiterzukommen. Die Frage sollte lauten " Warum wird die automatische Freigabe nicht für alle Objekte verwendet, sondern nur für die Beibehaltung und Freigabe? ".

Um diese Frage zu beantworten, sollten Sie zunächst wissen, wofür die automatische Freigabe sinnvoll ist. Nehmen wir an, Sie haben eine Klasse, die zwei Eigenschaften hat: Vorname und Nachname. Für jede gibt es einen Getter und einen Setter. Aber Sie brauchen auch eine Methode, die fullName zurückgibt, indem sie diese beiden Strings zu einem brandneuen String verkettet:

- (NSString *) fullName {
   NSString str = [[NSString alloc]initWithFormat:@"%@ %@", firstName, lastName];
   // this is not good until we put [str autorelease];
   return str;
}

Was ist an diesem Bild falsch? Der Referenzwert der zurückgegebenen Zeichenkette ist 1. Wenn Sie also kein Leck haben wollen, sollte der Aufrufer die Zeichenkette freigeben, wenn er fertig ist. Vom Standpunkt des Aufrufers aus gesehen hat er gerade einen Eigenschaftswert angefordert fullName . Er ist sich der Tatsache nicht bewusst, dass er ein brandneues Objekt erhalten hat, das er nach der Verwendung freigeben sollte, und nicht einen Verweis auf einen NSString, der intern von der Klasse gehalten wird!

Wenn wir die [str release] vor der Rückkehr, würde die Zeichenkette zerstört werden und die Methode würde Müll zurückgeben! An dieser Stelle verwenden wir [str autorelease] um das Objekt für die Freigabe zu einem späteren Zeitpunkt zu markieren (in der Regel, wenn die Ereignisverarbeitung abgeschlossen ist). Auf diese Weise erhält der Aufrufer sein Objekt und muss sich nicht darum kümmern, ob er es freigeben soll oder nicht.

Die Konvention ist es, autorelease für ein neues Objekt aufzurufen, bevor die Methode es an den Aufrufer zurückgibt. Ausnahmen sind Methoden mit Namen, die mit alloc , new o copy . In solchen Fällen wissen die Anrufer, dass ein brandneues Objekt für sie erstellt wurde und es ihre Pflicht ist, dieses Objekt freizugeben.

Die Freigabe durch eine automatische Freigabe zu ersetzen, ist eine schlechte Idee, da sich die Objekte stapeln und den Speicher sehr schnell verstopfen würden, insbesondere in Schleifen. Die Ressourcen auf dem iPhone sind begrenzt. Um den Speicherverbrauch zu minimieren, müssen Sie das Objekt freigeben, sobald Sie es nicht mehr benötigen.

5voto

Jon Thomason Punkte 579

Ich bin nicht der Meinung, dass es klug ist, die automatische Freigabe ganz zu vermeiden.

Cocoa Touch verwendet es intern recht häufig und in vielen Situationen ist es die einzige Möglichkeit, Speicher richtig zuzuweisen (ein gutes Beispiel sind wiederverwendbare Zellen in der Tabellenansicht). Wenn Sie verstehen, was hier passiert, ist der Autorelease-Pool ein großartiges Werkzeug, das Ihnen zur Verfügung steht. Das Wichtigste ist, dass die Blöcke erst zu einem späteren Zeitpunkt in der Ausführungsschleife freigegeben werden. Wenn Sie eine enge Schleife ohne Benutzerinteraktion ausführen und Blöcke für die automatische Freigabe anhäufen, wird Ihnen irgendwann der Speicher ausgehen.

Autorelease ist kein Ersatz für Garbage Collection (im iPhone SDK nicht verfügbar) und kann zu unangenehmen Dangling-Pointer-Fehlern führen (der Pointer scheint noch gut zu sein, wird dann aber zu einem unvorhersehbaren Zeitpunkt ungültig), ist aber auch sehr nützlich, um klaren und einfach zu wartenden Code zu schreiben. Betrachten Sie den folgenden Fall:

[aDictionary writeToFile:
     [documentsDirectory stringByAppendingPathComponent:@"settings.plist"]
              atomically:YES];

Der Pfadstring wird als Autorelease-Objekt erzeugt. Es ist nicht erforderlich, ein temporäres Objekt zu erstellen, so dass wir diesen Overhead vermeiden (und die Möglichkeit, dass wir vergessen, es freizugeben). Der Speicher wird vollständig freigegeben (keine Lecks), nur dass dies erst später in der Ausführungsschleife geschieht. Fragen Sie sich selbst: Werde ich Hunderte von ihnen zuweisen, bevor ich zur Benutzereingabe zurückkehre? Wenn nicht (wie in diesem Fall), ist die automatische Freigabe eine großartige Lösung, und tatsächlich ist diese NSString-Methode für die Arbeit mit Pfaden nur mit automatisch freigegebenem Speicher verfügbar.

Ich stimme mit dem oben genannten Poster überein, dass es eine sehr gute Idee ist, den Konventionen zu folgen und konsequent zu sein.

4voto

Brad Larson Punkte 169275

Ich tendiere dazu, Autorelease auf dem iPhone zu vermeiden, wo ich kann (wie Jon betont, kann man nicht immer darauf verzichten), einfach weil ich wissen möchte, dass die Objekte, mit denen ich arbeite, in dem Moment freigegeben werden, in dem ich sie nicht mehr brauche. Speicherbeschränkungen sind eines der größten Probleme, mit denen man auf dem Gerät konfrontiert wird, und ich glaube, dass sie die Ursache für die meisten Absturzprobleme sind, die man da draußen findet.

Wie von Apple hervorgehoben, besteht ein besonderes Problem bei der Verwendung von Objekten mit automatischer Freigabe innerhalb einer Schleife, da sie sich im Pool für die automatische Freigabe anhäufen. Sie müssen dann selbst entscheiden, wann Sie den Pool leeren oder ein Objekt erstellen/freigeben. Wenn man das bei jedem Durchlauf der Schleife macht, kann sich die Leistung verschlechtern, aber wenn man zu viele Durchläufe macht, kann das zu einer gefährlichen Speichernutzung führen. Ich bin noch dabei, dies in Molecules zu optimieren, da es beim Importieren großer (>2 MB) Textdateien aus der Protein Data Bank gelegentlich zu Speicherproblemen kommt. Ich konnte die Leistung verbessern, indem ich die automatisch freigegebenen Objekte minimiert habe, aber ich konnte sie nicht vollständig eliminieren.

Ein weiterer Bereich, auf den Sie achten sollten, ist die Verwendung von automatisch freigegebenen Objekten mit Threads. Verwenden Sie nach Möglichkeit keine automatisch freigegebenen Objekte, wenn es um Methoden geht, die auf einem Hintergrund-Thread ausgeführt werden, da der Pool zu zufälligen Zeiten geleert werden kann. Dies führt zu zeitweiligen Abstürzen, deren Aufspüren wirklich Spaß machen kann.

0voto

ryan.scott Punkte 2215

Ich würde dringend empfehlen, die automatische Freigabe wie die Pest zu meiden. Speicherverwaltungsfehler sind eine großartige Möglichkeit, Unmengen an Zeit und Geld zu verschwenden. Ich hatte die zweifelhafte Ehre, diesen Prozess bei alten Mac-Apps mehrmals durchlaufen zu müssen, und die Tatsache, dass das iPhone nur begrenzten Speicherplatz hat, bedeutet, dass man extrem vorsichtig sein muss, oder die App wird einfach instabil und stürzt oft ab... wie so viele der ersten Apps, die letzten Sommer veröffentlicht wurden.

Der einzige zuverlässige Weg, stabile iPhone-Programme zu schreiben, ist, den gesamten Speicher selbst zu verwalten, und zwar konsequent. Selbst wenn Sie der einzige Programmierer an Ihrem Projekt sind, werden Sie sich später dafür bedanken. Es kann schwierig sein, wenn Sie gelernt haben, in Sprachen zu programmieren, die "alles für Sie erledigen", aber es lohnt sich wirklich zu lernen, wie man es gut macht, wenn Sie es ernst meinen mit der Erstellung hochwertiger iPhone-Anwendungen.

CodeJaeger.com

CodeJaeger ist eine Gemeinschaft für Programmierer, die täglich Hilfe erhalten..
Wir haben viele Inhalte, und Sie können auch Ihre eigenen Fragen stellen oder die Fragen anderer Leute lösen.

Powered by:

X