2009-03-05 9 views
14

Estoy buscando una fuente principal (o una muy buena explicación) para respaldar la afirmación de que el uso de autorelease es peligroso o demasiado costoso cuando se escribe software para el iPhone.¿Por qué la liberación automática es especialmente peligrosa/costosa para las aplicaciones de iPhone?

Varios desarrolladores afirman esto, e incluso he escuchado que Apple no lo recomienda, pero no he podido encontrar ninguna fuente concreta para respaldarlo.

SO referencias:
autorelease-iphone
Why does this create a memory leak (iPhone)?

Nota: Puedo ver, desde un punto de vista conceptual, que autorelease es ligeramente más caro que una simple llamada a release, pero no creo que una pequeña penalización es suficiente para hacer que Apple lo recomiende.

¿Cuál es la historia real?

Respuesta

11

(? No puede aceptar su propia respuesta)

Bueno, después de todo eso, me las arreglé para encontrar una referencia de Apple Developer, añadido como una nota lateral cerca de la parte inferior de la página:

iPhone OS Nota: Debido a que en el iPhone OS una aplicación ejecuta en un entorno más con limitaciones de memoria, el uso de piscinas autorelease se desalentado en los métodos o bloques de código (por ejemplo, bucles) donde un crea aplicación tes muchos objetos. En su lugar, debe liberar explícitamente objetos siempre que sea posible.

Aún así, esto sugiere utilizar la autorrelease con cuidado, sin evitarlo por completo.

(y ahora para mi comentario)

Parece que hay una cierta cantidad de sobrecarga en el mantenimiento de la piscina. Leí this article lo que me llevaría probablemente a evitar la liberación automática tanto como sea posible porque prefiero que las cosas sean consistentes. Si tiene algo de memoria en autorelease y otra memoria que se maneja totalmente de forma manual, puede ser un poco más confuso.

+0

contento de ayudarme (me dieron algo para buscar :-) – TofuBeer

+1

Lo que no mencionan es muchas de las clases en la llamada de recuperación automática sobre los objetos que administran y por lo tanto en bucles estrechos necesitas crear y administrar tu propios grupos de autorreleases si está procesando incluso una cantidad modesta de datos. – rpetrich

+1

No creo que sea costoso mantener el grupo; más bien, es mejor no tener memoria asignada pero no utilizada más de lo necesario en un entorno de memoria limitada. Autorelease deja la memoria asignada más tiempo de lo necesario. – Paul

0

Yo recomendaría evitar la liberación automática como la peste. Los errores de administración de memoria son una gran manera de perder enormes cantidades de tiempo y dinero, he tenido el dudoso honor de pasar por el proceso muchas veces en aplicaciones antiguas de Mac, y el hecho de que el iPhone tenga restricciones de memoria significa que tiene tener mucho cuidado, o la aplicación será inestable y fallará a menudo ... como muchas de las primeras aplicaciones que se lanzaron el verano pasado.

La única manera confiable que he encontrado para escribir aplicaciones estables de iPhone es administrar toda tu memoria por ti mismo, y hacerlo de manera consistente. Incluso si usted es el único programador de su proyecto, se lo agradecerá más adelante. Puede ser difícil si aprendió a programar en idiomas que "se encargan de todo por usted", pero realmente vale la pena aprender a hacerlo bien si realmente quiere crear aplicaciones de calidad para iPhone.

+9

-1. Podría decir que es algo menos eficiente, pero la liberación automática no crea errores. Si sigue las reglas de administración de memoria (que incluyen liberación automática), no tendrá errores de memoria. Si no sigue las reglas, liberar cosas manualmente no lo salvará. – Chuck

5

No estoy de acuerdo en que sea prudente evitar la liberación automática.

Cocoa Touch utiliza con bastante frecuencia interna y para muchas situaciones es la única manera de asignar memoria correctamente (un buen ejemplo es reutilizables celdas de la vista de tabla). Si comprende lo que está sucediendo, el conjunto de autorrelease es una gran herramienta a su disposición. Lo principal para recordar es que los bloques no se liberan hasta algún punto posterior en el ciclo de ejecución. Si está ejecutando un ciclo cerrado sin interacción del usuario y está acumulando bloques de liberación automática, eventualmente se quedará sin memoria.

Autorelease no es un sustituto de la recolección de elementos no utilizados (no disponible en el SDK de iPhone) y puede provocar molestos errores de puntero (el puntero sigue pareciendo bueno, luego en algún punto impredecible no es válido), pero también muy útil para escribir código claro y fácil de mantener. Tenga en cuenta el siguiente caso:

[aDictionary writeToFile: 
    [documentsDirectory stringByAppendingPathComponent:@"settings.plist"] 
       atomically:YES]; 

La cadena de ruta se genera como un objeto de liberación automática. No estamos obligados a crear un objeto temporal, por lo que evitamos esa sobrecarga (y la posibilidad de que olvidemos lanzarlo). La memoria se liberará por completo (sin pérdidas), solo que sucederá más adelante en el ciclo de ejecución. Pregúntese: ¿voy a asignar cientos de estos antes de volver a la entrada del usuario? Si no (como sería el caso aquí), la liberación automática es una gran solución y, de hecho, este método NSString para trabajar con rutas solo está disponible utilizando la memoria liberada automáticamente.

Estoy de acuerdo con el cartel por encima de la siguiente convención y ser consistente es una muy buena idea.

4

Tiendo a evitar usar la liberación automática en el iPhone donde puedo (como Jon señala, no siempre se puede prescindir), simplemente porque me gusta saber que los objetos con los que estoy trabajando se liberan al instante No los necesito Las limitaciones de memoria son uno de los mayores problemas que enfrentarás en el dispositivo y creo que son la fuente de la mayoría de los problemas que encontrarás allí.

Como se destacó por Apple, un área particular de preocupación es cuando se utilizan objetos autoreleased dentro de cualquier tipo de bucle, porque van a acumularse dentro de la piscina autorelease. Luego debe administrar cuándo vaciar el grupo o crear/liberar uno. Si lo hace, cada pasada en el ciclo puede degradar el rendimiento, pero si pasa demasiadas veces sin él, podría generar un uso peligroso de la memoria. Todavía estoy modificando esto en Moléculas, porque hay problemas intermitentes de memoria al importar archivos de texto grandes (> 2 MB) del Banco de Datos de Proteínas. Pude mejorar el rendimiento al minimizar los objetos liberados automáticamente, pero no pude eliminarlos por completo.

Otra área a tener en cuenta es el uso de objetos autoreleased con hilos. Si es posible, no use objetos liberados automáticamente al tratar con métodos realizados en una cadena de fondo, ya que la agrupación se puede drenar en momentos aleatorios. Esto conduce a bloqueos intermitentes que pueden ser realmente divertidos de rastrear.

9

No es la cuestión de usar o no usar autorelease, porque en algunos casos autorelease es la única manera que obtendrá a través. La pregunta debería ser "¿Por qué no utilizar la liberación automática en todos los objetos, en lugar de usar retener y liberar?".

Para responder a eso, primero debe aprender lo que es un uso adecuado de autorelease. Digamos que tiene una clase que tiene dos propiedades: firstName y lastName. Hay un getter y un setter para cada uno. Pero también es necesario un método que devolvería fullName, mediante la concatenación de estos dos cadenas en una nueva cadena de marca:

- (NSString *) fullName { 
    NSString str = [[NSString alloc]initWithFormat:@"%@ %@", firstName, lastName]; 
    // this is not good until we put [str autorelease]; 
    return str; 
} 

¿Qué pasa con esa imagen? El recuento de referencias en la cadena devuelta es 1, por lo que si no desea filtrar, la persona que llama debe liberarlo cuando haya terminado.Desde el punto de vista de la persona que llama, acaba de solicitar un valor de propiedad fullName. ¡No tiene conocimiento del hecho de que recibió un nuevo objeto que debería liberar después de su uso, y no de una referencia a un NSString que pertenece a la clase!

Si ponemos el [str release] antes de devolver, la cadena se destruiría y el método devolvería la basura. Ahí es donde usamos [str autorelease], para marcar el objeto para su lanzamiento en un momento posterior (generalmente cuando se realiza el procesamiento del evento). De esa manera, la persona que llama obtiene su objeto, y no tiene que preocuparse de si debe liberarlo o no.

La convención es llamar a la liberación automática en un nuevo objeto antes de que el método lo devuelva a la persona que llama. Las excepciones son métodos con nombres que comienzan con alloc, new o copy. En tales casos, las personas que llaman saben que se les ha creado un nuevo objeto y que es su deber solicitar la liberación de ese objeto.

Reemplazar la liberación con la liberación automática es una mala idea, ya que los objetos se amontonarían y atascarían la memoria muy rápidamente, especialmente en los bucles. Los recursos en el iPhone son limitados, por lo que para minimizar el acaparamiento de memoria, es su deber liberar el objeto tan pronto como haya terminado con él.

Cuestiones relacionadas