Frage

So wie ich es verstehe, ist alles, was mit einem erstellt wurde zuordnen, neu, oder Kopieren muss manuell freigegeben werden.Zum Beispiel:

int main(void) {
    NSString *string;
    string = [[NSString alloc] init];
    /* use the string */
    [string release];
}

Meine Frage ist jedoch, wäre das nicht genauso gültig?:

int main(void) {
    NSAutoreleasePool *pool;
    pool = [[NSAutoreleasePool alloc] init];
    NSString *string;
    string = [[[NSString alloc] init] autorelease];
    /* use the string */
    [pool drain];
}
War es hilfreich?

Lösung

Ja, Ihr zweiter Code snippit ist vollkommen gültig.

Jedes Mal, -autorelease an ein Objekt gesendet wird, wird es an den Innen meisten Autofreigabepool hinzugefügt. Wenn der Pool leer ist, sendet er einfach -release auf alle Objekte im Pool.

Autorelease-Pools sind einfach eine Bequemlichkeit, die Sie bis „später“ zu senden -release aufschieben kann. Die „später“ kann an verschiedenen Orten geschehen, aber die am häufigsten in Cocoa GUI-Anwendungen am Ende des aktuellen Laufschleifenzyklus ist.

Andere Tipps

NSAutoreleasePool: drain vs. Veröffentlichung

Da die Funktion von drain und release scheinen Verwirrung zu verursachen, kann es sich lohnen, hier zu klären (obwohl dies in abgedeckt ist die Dokumentation ...).

Genau genommen aus der großen Bild Perspektive drain ist nicht entspricht release:

In einer Referenzzählung Umgebung, macht drain die gleichen Operationen wie release ausführen, so sind die beiden in diesem Sinne äquivalent. Um zu betonen, dies bedeutet, dass Sie nicht einen Pool auslaufen, wenn Sie drain verwenden, anstatt release.

In einer Garbage Collection-Umgebung ist release ein no-op. So hat es keine Wirkung. drain, auf der anderen Seite, enthält einen Hinweis auf die Sammler, die es „sammeln, wenn nötig“ sollte. So ist in einer Garbage Collection Umgebung, drain Verwendung hilft, die Systembilanz Sammlung fegt.

Wie bereits erwähnt, Ihr zweites Code-Snippet korrekt ist.

würde Ich mag eine prägnante Art und Weise der Verwendung des Autofreigabepools vorschlagen, die auf allen Umgebungen funktionieren (ref Zählen, GC, ARC) und vermeiden auch die Drain / release Verwirrung:

int main(void) {
  @autoreleasepool {
    NSString *string;
    string = [[[NSString alloc] init] autorelease];
    /* use the string */
  }
}

Im Beispiel oben Bitte beachten Sie den @autoreleasepool Block. Dies wird dokumentiert hier .

Nein, du bist falsch. In der Dokumentation wird deutlich, dass unter nicht-GC ist -Drain entspricht -release, die NSAutoreleasePool Sinn wird nicht geleckt werden.

Was ich von Apple lesen: „Am Ende des Autofreigabepool Block, Objekte, die eine Autorelease Nachricht innerhalb des Blocks empfangen werden eine Freigabenachricht-ein Objekt gesendet für jedes Mal eine Freigabenachricht empfängt es wurde eine Autorelease Nachricht innerhalb des Blocks gesendet.“

https://developer.apple. com / library / mac / Dokumentation / Kakao / konzeptueller / MemoryMgmt / Artikel / mmAutoreleasePools.html

Das Senden einer automatischen Freigabe anstelle einer Freigabe an ein Objekt verlängert die Lebensdauer dieses Objekts mindestens bis zur Entleerung des Pools selbst (dies kann länger dauern, wenn das Objekt anschließend beibehalten wird).Ein Objekt kann mehrmals in denselben Pool eingefügt werden. In diesem Fall erhält es für jedes Mal, wenn es in den Pool eingefügt wird, eine Freigabenachricht.

Ja und nein. Sie würden den String-Speicher am Ende der Freigabe aber „undichte“ das NSAutoreleasePool Objekts in dem Speicher durch anstelle der Freigabe mit Drain, wenn Sie diese gesammelt unter einem Müll laufen (nicht Speicher verwaltet) -Umgebung. Dieses „Leck“ macht einfach die Instanz von NSAutoreleasePool „nicht erreichbar“ wie jedes andere Objekt ohne starke Zeiger unter GC und das Objekt würde die nächsten GC läuft gereinigt, die sehr gut direkt sein könnte nach dem Aufruf von -drain:

  

Drain

     

In einer Müll gesammelt Umgebung, löst die Garbage Collection, wenn der Speicher seit letzter Sammlung zugeordnet ist größer als der aktuelle Schwellenwert; ansonsten verhält sich wie Release.   ...   In einer Garbage Collection Umgebung: diese Methode schließlich ruft objc_collect_if_needed.

Ansonsten ist es ähnlich, wie -release verhält sich unter nicht-GC, ja. Wie schon andere gesagt haben, ist -release ein no-op unter GC, so dass der einzige Weg, um sicher Funktionen auf den Pool, um richtig unter GC durch -drain ist, und -drain unter nicht-GC funktioniert genau wie -release unter nicht-GC und wohl kommuniziert seine Funktionalität mehr als gut klar.

Ich mag darauf hinweisen, dass Ihre Aussage „alles mit neuem genannt, alloc oder init“ nicht enthalten „init“ (sollte aber „kopieren“ enthalten), da „init“ Speicher nicht zuweisen, setzt sich nur bis die Objekt (Konstruktor Mode). Wenn Sie ein alloc'd Objekt und Ihre Funktion nur init als solche genannt empfangen, Sie würden es nicht loslassen:

- (void)func:(NSObject*)allocd_but_not_init
{
    [allocd_but_not_init init];
}

Das verbraucht nicht mehr Speicher als es bereits gestartet mit (unter der Annahme init Objekte nicht instanziiert, aber Sie sind nicht für die ohnehin verantwortlich).

Lizenziert unter: CC-BY-SA mit Zuschreibung
Nicht verbunden mit StackOverflow
scroll top