Es ist nicht dokumentiert, aber die Antwort erscheint Ja, auf OS X 10.9+ und iOS 7+ zu sein.
Die Objective-C-Laufzeit ist open-source, so dass Sie die Quelle lesen können, um zu sehen, was vor sich geht. Die neueste Version der Laufzeitumgebung (646, die mit OS X 10.10 und iOS 8 ausgeliefert wurde) fügt tatsächlich einen Pool hinzu, wenn Sie autorelease
ohne einen Pool im aktuellen Thread ausführen. In NSObject.mm:
static __attribute__((noinline))
id *autoreleaseNoPage(id obj)
{
// No pool in place.
assert(!hotPage());
if (obj != POOL_SENTINEL && DebugMissingPools) {
// We are pushing an object with no pool in place,
// and no-pool debugging was requested by environment.
_objc_inform("MISSING POOLS: Object %p of class %s "
"autoreleased with no pool in place - "
"just leaking - break on "
"objc_autoreleaseNoPool() to debug",
(void*)obj, object_getClassName(obj));
objc_autoreleaseNoPool(obj);
return nil;
}
// Install the first page.
AutoreleasePoolPage *page = new AutoreleasePoolPage(nil);
setHotPage(page);
// Push an autorelease pool boundary if it wasn't already requested.
if (obj != POOL_SENTINEL) {
page->add(POOL_SENTINEL);
}
// Push the requested object.
return page->add(obj);
}
Diese Funktion wird aufgerufen, wenn Sie den ersten Pool schieben (in diesem Fall schob die Sache ist POOL_SENTINEL
), oder Sie ohne Pool Autorelease. Wenn der erste Pool gedrückt wird, richtet er den Autorelease-Stack ein. Aber wie Sie aus dem Code sehen, solange die Umgebungsvariable DebugMissingPools
nicht gesetzt ist (es ist nicht standardmäßig eingestellt), wenn Autorelease ohne Pool gemacht wird, richtet sie auch den Autorelease-Stack ein, und schiebt dann einen Pool (drückt a POOL_SENTINEL
).
Ähnlich (es ist ein wenig schwer zu folgen, ohne auf den anderen Code zu schauen, aber das ist der relevante Teil), wenn der Thread zerstört wird (und der Thread-Local Storage zerstört wird), gibt es alles im Autorelease-Stack (das ist, was die pop(0);
der Fall ist), so dass es verlässt sich nicht auf dem Benutzer den letzten Pool Pop:
static void tls_dealloc(void *p)
{
// reinstate TLS value while we work
setHotPage((AutoreleasePoolPage *)p);
pop(0);
setHotPage(nil);
}
die vorherige Version der Common Language Runtime (551.1, die mit OS kam X 10.9 und iOS 7), auch tat dies, wie Sie von seinem NSObject.mm sehen können:
Aber die vorherige Version (532.2, die mit OS X 10 kam.8 und iOS 6), does not:
static __attribute__((noinline))
id *autoreleaseSlow(id obj)
{
AutoreleasePoolPage *page;
page = hotPage();
// The code below assumes some cases are handled by autoreleaseFast()
assert(!page || page->full());
if (!page) {
assert(obj != POOL_SENTINEL);
_objc_inform("Object %p of class %s autoreleased "
"with no pool in place - just leaking - "
"break on objc_autoreleaseNoPool() to debug",
obj, object_getClassName(obj));
objc_autoreleaseNoPool(obj);
return NULL;
}
do {
if (page->child) page = page->child;
else page = new AutoreleasePoolPage(page);
} while (page->full());
setHotPage(page);
return page->add(obj);
}
Beachten Sie, dass die oben genannten Arbeiten für alle pthread
s, nicht nur NSThread
s.
Also im Grunde, wenn Sie auf OS X 10.9+ oder iOS 7+ laufen, sollte Autoreleasing auf einem Thread ohne einen Pool nicht zu einem Leck führen. Dies ist nicht dokumentiert und stellt ein internes Implementierungsdetail dar. Seien Sie also vorsichtig, wenn Sie sich darauf verlassen, da Apple es in einem zukünftigen Betriebssystem ändern könnte. Ich sehe jedoch keinen Grund, warum sie diese Funktion entfernen würden, da sie einfach ist und nur Vorteile und keine Nachteile hat, es sei denn, sie schreiben die Art und Weise, wie Autorelease-Pools funktionieren oder etwas anderes, komplett um.
Wie sagen Sie, dass Ihr mein Objekt freigegeben wird? –
können Sie die erforderlichen Informationen erhalten? –
weil ich einen Haltepunkt in Objekt "meine" Dealloc-Methode – eliudnis