¿Cómo funciona el pool de autorelease NSAutoreleasePool?

Según tengo entendido, cualquier cosa creada con una asignación , nueva o copia debe ser liberada manualmente. Por ejemplo:

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

Mi pregunta, sin embargo, es si esto no fuera tan válido ?:

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

Sí, su segundo snippit de código es perfectamente válido.

Cada vez que se envía un aviso a un objeto, se agrega al grupo de autorrelease más interno. Cuando se drena la agrupación, simplemente envía -extrae a todos los objetos en la agrupación.

Los pools Autorelease son simplemente una conveniencia que le permite diferir el envío-liberación hasta “más tarde”. Que “más tarde” puede suceder en varios lugares, pero la más común en las aplicaciones Cocoa GUI se encuentra al final del ciclo de ciclo de ejecución actual.

NSAutorelease: drenaje vs. lanzamiento

Dado que la función de drain y release parece estar causando confusión, puede valer la pena aclarar aquí (aunque esto está cubierto en la documentación …).

Estrictamente hablando, desde el punto de vista de la perspectiva general no es equivalente a la release :

En un entorno contado por referencia, drain realiza las mismas operaciones que release , por lo que los dos son en ese sentido equivalentes. Para enfatizar, esto significa que no se pierde un grupo si usa drain lugar de release .

En un entorno recolectado de basura, el release es operativo. Por lo tanto, no tiene ningún efecto. drain , por otro lado, contiene una pista para el recolector que debería “recostackr si es necesario”. Por lo tanto, en un entorno recolectado de basura, usar drain ayuda al sistema a equilibrar los barridos de recolección.

Como ya se señaló, su segundo fragmento de código es correcto.

Me gustaría sugerir una forma más concisa de usar el grupo de autorrelease que funciona en todos los entornos (recuento de ref, GC, ARC) y también evita la confusión de drenaje / liberación:

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

En el ejemplo anterior, tenga en cuenta el bloque @autoreleasepool . Esto está documentado aquí .

No, tu estas equivocado. La documentación establece claramente que, en el caso de que no exista GC, -drain es equivalente a -release, lo que significa que NSAutoreleasePool no se filtrará.

Encontré que este enlace daba la mejor explicación sobre cuándo y cómo usar NSAutoReleasePool: AutoReleasePool

Si tu código es perfecto, si usas recolección de basura bastará con poner la cadena en cero cuando hayas terminado con ella. La recolección de basura no es buena para el rendimiento de su aplicación, por lo que no recomendaría su uso: P

Lo que leí de Apple: “Al final del bloque de bloque de liberación automática, los objetos que recibieron un mensaje de liberación automática dentro del bloque reciben un mensaje de liberación: un objeto recibe un mensaje de liberación cada vez que se envía un mensaje de liberación automática dentro del bloque. ”

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

al enviar la liberación automática en lugar de liberarlo a un objeto, se extiende la vida útil de ese objeto al menos hasta que se drene el conjunto (puede ser más largo si el objeto se retiene posteriormente). Un objeto puede colocarse en el mismo grupo varias veces, en cuyo caso recibe un mensaje de liberación cada vez que se coloca en el grupo.

Si y no. Usted terminaría liberando la memoria de cadena pero “filtrando” el objeto NSAutoreleasePool en la memoria mediante el uso de drain en lugar de release si ejecutó esto en un entorno recogido de basura (no gestionado en memoria). Esta “fuga” simplemente hace que la instancia de NSAutoreleasePool “inalcanzable” como cualquier otro objeto sin punteros fuertes en GC, y el objeto se limpiará la próxima vez que se ejecuta GC, que podría ser muy bien después de la llamada a -drain :

desagüe

En un entorno recolectado de basura, desencadena la recolección de basura si la memoria asignada desde la última colección es mayor que el umbral actual; de lo contrario se comportará como lanzamiento. … En un entorno recolectado de basura, este método finalmente llama a objc_collect_if_needed .

De lo contrario, es similar a cómo-la -release comporta bajo no GC, sí. Como otros han declarado, ” -release es una -drain no -drain bajo GC, por lo que la única manera de asegurarse de que el grupo funcione correctamente bajo GC es mediante -drain , y -drain bajo GC funciona exactamente igual que -release bajo GC, y podría decirse que comunica su funcionalidad más claramente también.

Debo señalar que su frase “todo lo que se llame con nuevo, alloc o init” no debe incluir “init” (pero debe incluir “copiar”), porque “init” no asigna memoria, solo configura el objeto (constructor) Moda). Si recibiste un objeto asignado y tu función solo llama a init como tal, no lo liberarías:

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

Eso no consume más memoria de la que ya comenzó (suponiendo que init no instancia los objetos, pero de todos modos no es responsable de ellos).