Domanda

A quanto ho capito, qualsiasi cosa creata con un file alloc, nuovo, O copia deve essere rilasciato manualmente.Per esempio:

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

La mia domanda, però, è: non sarebbe altrettanto valido?:

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

Soluzione

Sì, il tuo secondo frammento di codice è perfettamente valido.

Ogni volta che -autorelease viene inviato a un oggetto, viene aggiunto al pool di rilascio automatico più interno.Quando il pool viene svuotato, invia semplicemente -release a tutti gli oggetti nel pool.

I pool di rilascio automatico sono semplicemente una comodità che consente di rinviare l'invio -release a "più tardi".Questo "successivo" può verificarsi in diversi punti, ma il più comune nelle app Cocoa GUI è alla fine del ciclo di esecuzione corrente.

Altri suggerimenti

Pool di rilascio automatico NS:drenare vs.pubblicazione

Poiché la funzione di drain E release sembrano causare confusione, potrebbe valere la pena chiarirlo qui (anche se questo è trattato in la documentazione...).

A rigor di termini, dalla prospettiva del quadro generale drain È non equivalente a release:

In un ambiente con conteggio dei riferimenti, drain esegue le stesse operazioni di release, quindi i due sono in questo senso equivalenti.Per sottolineare, questo significa che lo fai non perdita di una piscina se la usi drain piuttosto che release.

In un ambiente di raccolta dei rifiuti, release è una operazione vietata.Quindi non ha alcun effetto. drain, d'altra parte, contiene un suggerimento al collezionista che dovrebbe "raccogliere se necessario".Quindi, in un ambiente di raccolta dei rifiuti, utilizzando drain aiuta il sistema a bilanciare le operazioni di raccolta.

Come già sottolineato, il tuo secondo snippet di codice è corretto.

Vorrei suggerire un modo più conciso di utilizzare il pool di rilascio automatico che funzioni su tutti gli ambienti (conteggio dei riferimenti, GC, ARC) ed eviti anche la confusione di drenaggio/rilascio:

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

Nell'esempio sopra si prega di notare il @autoreleasepool bloccare.Questo è documentato Qui.

No, ti sbagli.La documentazione afferma chiaramente che sotto non GC, -drain è equivalente a -release, il che significa che NSAutoreleasePool lo farà non essere trapelato.

Cosa ho letto da Apple:"Alla fine del blocco del pool di rilascio automatico, agli oggetti che hanno ricevuto un messaggio di rilascio automatico all'interno del blocco viene inviato un messaggio di rilascio: un oggetto riceve un messaggio di rilascio ogni volta che gli è stato inviato un messaggio di rilascio automatico all'interno del blocco."

https://developer.apple.com/library/mac/documentation/cocoa/conceptual/MemoryMgmt/Articles/mmAutoreleasePools.html

l'invio di rilascio automatico invece di rilascio a un oggetto estende la durata di quell'oggetto almeno fino a quando il pool stesso viene svuotato (potrebbe essere più lungo se l'oggetto viene successivamente conservato).Un oggetto può essere inserito più volte nello stesso pool, nel qual caso riceve un messaggio di rilascio ogni volta che viene inserito nel pool.

Sì e no.Finiresti per rilasciare la memoria della stringa ma "perdere" l'oggetto NSAutoreleasePool in memoria utilizzando drain invece di release se lo eseguissi in un ambiente di garbage collection (non gestito dalla memoria).Questa "perdita" rende semplicemente l'istanza di NSAutoreleasePool "irraggiungibile" come qualsiasi altro oggetto senza puntatori forti sotto GC, e l'oggetto verrebbe ripulito alla successiva esecuzione di GC, che potrebbe benissimo essere direttamente dopo la chiamata a -drain:

drenare

In un ambiente di Garbage Collection, attiva la Garbage Collection se la memoria allocata dall'ultima raccolta è maggiore della soglia corrente;altrimenti si comporta come un rilascio....In un ambiente di raccolta dei rifiuti, questo metodo alla fine chiama objc_collect_if_needed.

Altrimenti, è simile a come -release si comporta in condizioni non-GC, sì.Come altri hanno affermato, -release è una operazione vietata in GC, quindi l'unico modo per assicurarsi che il pool funzioni correttamente in GC è attraverso -drain, E -drain sotto non GC funziona esattamente come -release sotto non GC e probabilmente comunica anche la sua funzionalità in modo più chiaro.

Dovrei sottolineare che la tua affermazione "qualsiasi cosa chiamata con new, alloc o init" non dovrebbe includere "init" (ma dovrebbe includere "copia"), perché "init" non alloca memoria, imposta solo l'oggetto (costruttore moda).Se ricevessi un oggetto allocato e la tua funzione chiamasse solo init come tale, non lo rilasceresti:

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

Ciò non consuma più memoria di quella con cui hai già iniziato (supponendo che init non istanzia oggetti, ma non ne sei comunque responsabile).

Autorizzato sotto: CC-BY-SA insieme a attribuzione
Non affiliato a StackOverflow
scroll top