2011-06-30 14 views
9

He estado programando en el iPhone durante bastante tiempo y he tenido malas experiencias con la gestión de la memoria. Me preguntaba si la siguiente forma es una buena manera de liberar memoria.¿Es esta una buena manera de liberar memoria?

int count = [someObject retainCount]; 

for (int i = 0; i < count; i ++) 
{ 
[someObject release]; 
} 

Este método fue un acto de desesperación en algunas situaciones (en particular UIWebViews) que había enfrentado. La variable retainCount se reduce a cero, lo que liberará la memoria que está utilizando. El método está un poco sucio, pero ¿hay algún cuello de botella asociado?

+5

No, no es una buena manera de liberar memoria. – Sneakyness

+0

Lea la documentación de administración de memoria de Apple lo antes posible, que explica cómo administra la memoria. Nunca hagas esto –

Respuesta

28

no se debe confiar en la retainCount porque hay posibilidad de retener el objeto iOS marcos,

Lea a continuación lo que Apple decir sobre retainCount.

Importante: Este método es típicamente de ningún valor en la depuración de problemas de gestión de memoria . Ya que cualquier número de objetos marco puede haber retenido un objeto con el fin de mantener las referencias a ella, mientras que al mismo tiempo piscinas autorelease pueden ser la celebración de cualquier número de liberaciones diferidos en un objeto , es muy poco probable que usted puede obtener información útil de este método .

Para comprender las reglas fundamentales de la gestión de memoria que debe cumplir, lea "Memory Management Rules". Para diagnosticar los problemas de gestión de memoria, utilice una herramienta adecuada:

+3

Sin mencionar la posibilidad de que * uno de tus propios objetos * también retenga el objeto. No importa de quién es el objeto; si apuñalas al objeto hasta que muere mientras algo todavía se aferra a él, causarás un bloqueo más adelante. –

3

No debe confiar en el valor de retainCount. Debe lanzar tan a menudo como llame al alloc y copy.

Editar: y new y retain.

+0

Y 'retener' también. – beryllium

+0

y 'new' también :) – beryllium

+4

NARC ... nueva copia de retención alloc –

14

Este código es un absoluto no-go. Simplemente oculta tus errores de programación, y lo hace de muy mala manera.

Conozca la gestión adecuada de la memoria. No hay sustituto.

Aquí está el memory management programming guide. Vale la pena leer más de una vez.

+1

Esto. ¡Mil veces esto! –

7

Como han mencionado otros, -retainCount es prácticamente inútil. Cuando es nuevo en el recuento de administración/referencia de memoria en Objective-C, a veces puede ser tentador intentar usar - retainCount para ayudar a entender cómo funciona el recuento de referencias, pero en realidad puede ser (al parecer) confuso en el mejor de los casos.

El código que ha publicado es potencialmente peligroso, en sí mismo, dependiendo del contexto que lo rodea de cómo se usa someObject. También puede ser peligroso cuando se aplica a otras situaciones que no esperaba. Tómese el NSString s constante creado con la directiva de compilación @"a string": estas cadenas se crean y están diseñadas para que nunca se publiquen. Por lo tanto la aplicación de su código como en el siguiente ejemplo se traduciría en un bucle infinito:

int main (int argc, const char * argv[]) { 
    NSAutoreleasePool * pool = [[NSAutoreleasePool alloc] init]; 

    NSString *string = @"theString"; 

    NSLog(@"retainCount == %lu", (unsigned long)[string retainCount]); 

    for (NSUInteger i = 0; i < [string retainCount]; i++) { 
     [string release]; 
    } 

    [pool drain]; 
    return 0; 
} 

Esta impresora:

2011-06-30 08:40:16.287 retainCount[35505:a0f] retainCount == 1152921504606846975

y luego entra en un bucle infinito.

+0

Oooh, no había pensado en estática ni en singleton, ¡buena respuesta! – deanWombourne

+0

No soltaría una constante. Sé que el lanzamiento debe ser llamado solo para nuevo, alloc, copy y retener. Es solo que en algunas situaciones algunos objetos han retenido los conteos más de lo que esperaba. El método que publiqué fue solo una solución para esos pocos casos. Pero a partir de las respuestas publicadas, creo que es mejor rastrear por qué se conserva en lugar de utilizar ese método :). –

+2

Cuando se trata de retener los conteos, "más de lo que esperaba" no implica "incorrecto". Tampoco significa necesariamente que haya algo * usted * que deba hacer para reducirlo: simplemente asegúrese de que se ocupen de sus propias responsabilidades, sus propias llamadas nuevas/alloc/retener/copiar estén equilibradas con una publicación (automática) correspondiente, y todo estará bien. Para objetos que no sean los suyos, recuerde: lo que sucede en NSVegas, permanece en NSVegas. :-) –

6

No puedo decir NO enfáticamente!

Tome este ejemplo de su código en acción:

// Create an autoreleased object 
MyObject *myObject = [[[MyObject alloc] init] autorelease]; 

// Run your code to make it dealloc itself 
int count = [myObject retainCount]; 
for (int i = 0; i < count; i ++) 
    [myObject release]; 

Su código obligaría myObject que se dealloced.

Sin embargo, myObject también se ha incluido en el grupo de liberación automática. Tan pronto como el grupo haya comenzado a liberar sus objetos, su aplicación se bloqueará porque myObject ya no existe.

La regla es simple: Liberación de llamada cada vez que utiliza init, new o copy. De lo contrario, no es tu problema.

+0

Lo mejor de esta respuesta es que describió un problema que no es incluso el problema que tiene tu código de muestra. Es por eso que debe confiar en las reglas de recuento de referencias (o recuento de referencias automáticas o recolección de basura) en lugar de intentar adivinar los marcos. –

+0

Estoy confundido: la llamada a stringWithString agregará myString al grupo de autorrelease; esto intentará liberarlo en algún momento en el futuro. ¿Qué me estoy perdiendo?(Aunque para ser claro, definitivamente no estoy diciendo que este es el único problema que tiene el código OP, esto es simplemente un ejemplo en uno) – deanWombourne

+0

'+ stringWithString:/* una instancia de NSConstantString * /' simplemente devolverá la constante cadena, por lo que en realidad está tratando de liberar un objeto estático. Como dije, la parte importante es que está mal: tratar de ser inteligente acerca de cómo está mal solo terminará en lágrimas. –

Cuestiones relacionadas