Non è documentato, ma la risposta sembra essere sì , su OS X 10.9+ e iOS 7+.
Il runtime Objective-C è open-source in modo da poter leggere il codice sorgente per vedere cosa sta succedendo. L'ultima versione del runtime (646, fornita con OS X 10.10 e iOS 8) aggiunge effettivamente un pool se si esegue uno autorelease
senza un pool sul thread corrente. 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);
}
Questa funzione viene chiamata quando si preme la prima piscina (nel qual caso la cosa ha spinto è POOL_SENTINEL
), oppure si autorelease senza piscina. Quando viene premuto il primo pool, imposta lo stack di autorelease. Ma come si vede dal codice, purché la variabile ambientale DebugMissingPools
non sia impostata (non è impostata per impostazione predefinita), quando l'autorelease viene eseguito senza pool, imposta anche lo stack di autorelease e quindi spinge un pool (spinge un POOL_SENTINEL
).
Analogamente, (è un po 'difficile da seguire senza guardare l'altro codice, ma questa è la parte rilevante) quando il thread viene distrutto (e il Thread-Local Storage è distrutto (che è ciò che il pop(0);
fa) in modo che non si basa su l'utente al pop all'ultimo piscina:
static void tls_dealloc(void *p)
{
// reinstate TLS value while we work
setHotPage((AutoreleasePoolPage *)p);
pop(0);
setHotPage(nil);
}
la precedente versione del runtime (551.1, che è venuto con OS X 10.9 e iOS 7), anche ha fatto questo, come potete vedere dal suo NSObject.mm:
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) {
// No pool. Silently push one.
assert(obj != POOL_SENTINEL);
if (DebugMissingPools) {
_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;
}
push();
page = hotPage();
}
do {
if (page->child) page = page->child;
else page = new AutoreleasePoolPage(page);
} while (page->full());
setHotPage(page);
return page->add(obj);
}
Ma la versione precedente (532.2, fornita con OS X 10.8 e 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);
}
Nota che i lavori di cui sopra per eventuali pthread
s, non solo NSThread
s.
Quindi, in pratica, se si utilizza OS X 10.9+ o iOS 7+, l'esecuzione automatica su un thread senza pool non dovrebbe causare perdite. Questo non è documentato ed è un dettaglio di implementazione interno, quindi fai attenzione a fare affidamento su ciò in quanto Apple potrebbe cambiarlo in un sistema operativo futuro. Tuttavia, non vedo alcun motivo per cui rimuovono questa funzionalità in quanto è semplice e ha solo vantaggi e svantaggi, a meno che non vengano completamente riscritti nel modo in cui i pool di autorelease funzionano o qualcosa del genere.
Come stai dicendo che il mio oggetto viene rilasciato? –
sei in grado di ottenere le informazioni richieste? –
perché ho un punto di interruzione nell'oggetto metodo dealloc "mio" – eliudnis