Soweit ich weiß, muss alles, was mit einer Zuordnung , einer neuen oder einer Kopie erstellt wurde , manuell freigegeben werden. Beispielsweise:
int main(void) {
NSString *string;
string = [[NSString alloc] init];
/* use the string */
[string release];
}
Meine Frage ist jedoch, ob dies nicht genauso gültig ist?:
int main(void) {
NSAutoreleasePool *pool;
pool = [[NSAutoreleasePool alloc] init];
NSString *string;
string = [[[NSString alloc] init] autorelease];
/* use the string */
[pool drain];
}
objective-c
memory-management
nsautoreleasepool
foundationkit
James Sumners
quelle
quelle
an object
sollte seinan object that is a subclass of NSObject or NSProxy and doesn't override -autorelease
.NSAutoreleasePool: Drain vs. Release
Da die Funktion von
drain
undrelease
Verwirrung zu stiften scheint, kann es hier sinnvoll sein, dies zu klären (obwohl dies in der Dokumentation behandelt wird ...).Streng genommen, aus der großen Bild Perspektive
drain
ist nicht gleichbedeutend mitrelease
:Führt in einer Umgebung mit Referenzzählung
drain
dieselben Operationen aus wierelease
, sodass die beiden in diesem Sinne äquivalent sind. Um zu betonen, Das heißt , Sie nicht undicht einen Pool , wenn Sie verwendendrain
stattrelease
.In einer Müllsammelumgebung
release
ist ein No-Op. Somit hat es keine Wirkung.drain
enthält andererseits einen Hinweis an den Sammler, dass er "bei Bedarf sammeln" sollte. In einer Umgebung, in der Müll gesammelt wird,drain
hilft die Verwendung des Systems dabei, das Sammeln von Sammlungen auszugleichen.quelle
NSAutoreleasePool
. Dies liegt daran, dass Pools wie ein Stapel funktionieren. Durch das Instanziieren eines Pools wird dieser Pool an die Spitze des Autorelease-Poolstapels des Threads verschoben.-release
bewirkt, dass dieser Pool aus dem Stapel herausspringt UND alle Pools, die darauf geschoben wurden, aber aus irgendeinem Grund nicht aufgetaucht sind.Wie bereits erwähnt, ist Ihr zweites Code-Snippet korrekt.
Ich möchte eine prägnantere Methode für die Verwendung des Autorelease-Pools vorschlagen, die in allen Umgebungen (Ref Counting, GC, ARC) funktioniert und auch die Verwirrung zwischen Drain und Release vermeidet:
Beachten Sie im obigen Beispiel den @ autoreleasepool- Block. Dies ist hier dokumentiert .
quelle
@autoreleasepool
Block mit ARC verwenden.Nein, du liegst falsch. In der Dokumentation wird klargestellt, dass -drain unter Nicht-GC gleichbedeutend mit -release ist, was bedeutet, dass der NSAutoreleasePool nicht durchgesickert ist.
quelle
NSAutoreleasePool
Was ich von Apple gelesen habe: "Am Ende des Autorelease-Poolblocks erhalten Objekte, die eine Autorelease-Nachricht innerhalb des Blocks empfangen haben, eine Release-Nachricht. Ein Objekt erhält eine Release-Nachricht für jedes Mal, wenn eine Autorelease-Nachricht innerhalb des Blocks gesendet wurde. ""
https://developer.apple.com/library/mac/documentation/cocoa/conceptual/MemoryMgmt/Articles/mmAutoreleasePools.html
quelle
Das Senden einer Autorelease anstelle einer Freigabe an ein Objekt verlängert die Lebensdauer dieses Objekts mindestens bis zum Entleeren des Pools selbst (es kann länger sein, wenn das Objekt anschließend beibehalten wird). Ein Objekt kann mehrmals in denselben Pool gestellt werden. In diesem Fall erhält es für jedes Mal, wenn es in den Pool gelegt wurde, eine Freigabemeldung.
quelle
Ja und nein. Sie würden am Ende den String-Speicher freigeben, aber das NSAutoreleasePool-Objekt in den Speicher "verlieren", indem Sie Drain anstelle von Release verwenden, wenn Sie dies in einer durch Müll gesammelten (nicht speicherverwalteten) Umgebung ausführen. Dieses "Leck" macht die Instanz von NSAutoreleasePool einfach "nicht erreichbar" wie jedes andere Objekt ohne starke Zeiger unter GC, und das Objekt würde beim nächsten Ausführen von GC bereinigt, was sehr wohl direkt nach dem Aufruf von
-drain
:Ansonsten ist es ähnlich wie
-release
bei Nicht-GC, ja. Wie andere angegeben haben,-release
handelt es sich bei GC um ein No-Op. Die einzige Möglichkeit, um sicherzustellen, dass der Pool unter GC ordnungsgemäß funktioniert, besteht darin-drain
, und-drain
unter Nicht-GC funktioniert genau wie-release
unter Nicht-GC und kommuniziert seine Funktionalität möglicherweise klarer als Gut.Ich sollte darauf hinweisen, dass Ihre Anweisung "alles, was mit new, alloc oder init aufgerufen wird" nicht "init" enthalten sollte (sondern "copy"), da "init" keinen Speicher zuweist, sondern nur das Objekt (Konstruktor) einrichtet Mode). Wenn Sie ein zugewiesenes Objekt erhalten und Ihre Funktion nur init als solches aufgerufen hätte, würden Sie es nicht freigeben:
Das verbraucht nicht mehr Speicher als Sie bereits begonnen haben (vorausgesetzt, init instanziiert keine Objekte, aber Sie sind trotzdem nicht dafür verantwortlich).
quelle
-[NSAutoreleasePool release]
In einer Müllsammelumgebung ist ein No-Op.-[NSAutoreleasePool drain]
funktioniert sowohl in referenzgezählten als auch in müllsammelten Umgebungen.