Pregunta

Según tengo entendido, cualquier cosa creada con un asignar, nuevo, o Copiar debe liberarse manualmente.Por ejemplo:

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

Mi pregunta, sin embargo, ¿no sería esto igual de válido?:

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

Solución

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

Cada vez que se envía -autorelease a un objeto, se agrega al grupo de liberación automática más interno.Cuando se drena la piscina, simplemente envía -liberación a todos los objetos de la piscina.

Los grupos de liberación automática son simplemente una conveniencia que le permite posponer el envío y la liberación hasta "más tarde".Ese "más tarde" puede ocurrir en varios lugares, pero lo más común en las aplicaciones Cocoa GUI es al final del ciclo de ejecución actual.

Otros consejos

NSAutoreleasePool:drenaje vs.liberar

Dado que la función de drain y release parecen estar causando confusión, puede que valga la pena aclararlo aquí (aunque esto se trata en la documentación...).

Estrictamente hablando, desde la perspectiva general drain es no equivalente a release:

En un entorno contado de referencias, drain realiza las mismas operaciones que release, por lo que los dos son equivalentes en ese sentido.Para enfatizar, esto significa que no no gotear una piscina si usa drain en vez de release.

En un ambiente donde se recolecta basura, release es una operación no operativa.Por lo tanto no tiene ningún efecto. drain, por otro lado, contiene una pista para el coleccionista de que debe "recolectar si es necesario".Por lo tanto, en un entorno de recolección de basura, el uso drain ayuda al sistema a equilibrar los barridos de recaudación.

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

Me gustaría sugerir una forma más concisa de utilizar el grupo de liberación automática que funcione en todos los entornos (recuento de referencias, GC, ARC) y que también evite 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 la @autoreleasepool bloquear.esto esta documentado aquí.

No, tu estas equivocado.La documentación establece claramente que en condiciones que no son GC, -drain es equivalente a -release, lo que significa que NSAutoreleasePool no ser filtrado.

Lo que leí de Apple:"Al final del bloque del grupo 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 le envió un mensaje de liberación automática dentro del bloque".

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

enviar la liberación automática en lugar de la liberación a un objeto extiende la vida útil de ese objeto al menos hasta que se drena el grupo (puede ser más largo si el objeto se retiene posteriormente).Un objeto se puede colocar 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.Terminaría liberando la memoria de la cadena pero "filtrando" el objeto NSAutoreleasePool en la memoria usando drenaje en lugar de liberación si ejecutara esto en un entorno de recolección de basura (no administrado de memoria).Esta "fuga" simplemente hace que la instancia de NSAutoreleasePool sea "inalcanzable" como cualquier otro objeto sin punteros fuertes bajo GC, y el objeto se limpiará la próxima vez que se ejecute GC, lo que muy bien podría ser directamente después de la llamada a -drain:

drenar

En un entorno de recolección de basura, activa la recolección de basura si la memoria asignada desde la última recolección es mayor que el umbral actual;de lo contrario se comporta como liberación....En un entorno de recolección de basura, este método finalmente llama objc_collect_if_needed.

De lo contrario, es similar a cómo -release se comporta sin GC, sí.Como otros han dicho, -release no es operativo bajo GC, por lo que la única forma de asegurarse de que el grupo funcione correctamente bajo GC es a través de -drain, y -drain bajo no GC funciona exactamente igual -release bajo no GC, y posiblemente también comunica su funcionalidad más claramente.

Debo señalar que su declaración "cualquier cosa llamada con new, alloc o init" no debería incluir "init" (pero debería incluir "copiar"), porque "init" no asigna memoria, solo configura el objeto (constructor moda).Si recibió un objeto asignado y su función solo llamó a init como tal, no lo liberaría:

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

Eso no consume más memoria de la que ya empezaste (suponiendo que init no crea instancias de objetos, pero de todos modos no eres responsable de ellos).

Licenciado bajo: CC-BY-SA con atribución
No afiliado a StackOverflow
scroll top