iphone - perdido - ios versiones
En CocoaTouch(iPhone OS), ¿cómo puedo encontrar/eliminar las fugas que la herramienta Instruments Leak no encuentra? (5)
También debe ejecutar su aplicación con los instrumentos del monitor de memoria para ver el uso general del sistema en el dispositivo.
Tengo una aplicación de iPhone que funciona muy bien en el simulador. Responde bien a las advertencias de memoria al deshacerse de todo lo que no es absolutamente esencial. Cuando lo ejecuto en el dispositivo, funciona bien. Pero después de una cierta cantidad de uso, se bloquea con el código de error 101, que, por lo que puedo decir, es el sistema operativo que lo mata debido al uso de la memoria. Puedo ver la advertencia de memoria (la estoy registrando), y mi aplicación responde a ella, pero muere poco después.
Si miro la aplicación en Instruments (ya sea en el dispositivo o en sim), no encuentra ninguna fuga. Además, el uso de la memoria neta está en el rango de 600-700k bytes. La transición desde las diferentes vistas de mi aplicación aumenta el uso de la memoria (como se esperaba), pero cuando las vistas y los controladores se liberan y se desglosan, el uso de la memoria nunca es tan bajo como antes. Sin embargo, la adición generalmente es solo algo en el rango de 1000-2000 bytes. Entonces, mientras Leaks no me muestra ninguna fuga, sospecho que hay un problema en alguna parte. También miré todos los objetos que estoy asignando, y todos parecen recuperarse como se esperaba. Los únicos objetos que veo que siguen aumentando son GeneralBlock-N (donde N es un número)
¿No debería prestar atención a la cifra de uso neto de Instruments? ¿Cuáles serían los próximos pasos para tratar de diagnosticar el problema?
AGREGADO: No estoy haciendo ninguna llamada a malloc () o cualquier biblioteca de CoreFoundation que devolvería un búfer del que soy responsable. Las únicas llamadas que no son de Obj-C que estoy realizando son las declaraciones de registro de NSLog.
Las filtraciones solo encuentran memoria a la que no hace referencia ningún elemento, pero que aún conserva.
Lo que está viendo es que ha dejado memoria retenida, y todavía hace referencia a algo.
Una cosa que debes buscar especialmente, es que si pasas una referencia de una clase a otra cosa como delegado, la liberas en tu método dealloc.
Del mismo modo, si se ha suscrito a alguna notificación, debe darse de baja en viewWillDisappear: (si utiliza el método general de desuscripción en un controlador de vista, no olvide volver a suscribirse a la notificación de advertencia de memoria.
Los temporizadores son de la misma manera, desactívelos cuando se va una vista y vuelva a habilitarlos cuando vuelva la vista (a menos que, por supuesto, necesite un temporizador ejecutándose todo el tiempo que su aplicación se esté ejecutando).
Básicamente, desconfíe de cualquier cosa a la que le dé una referencia de una clase, y trate de descubrir cómo puede eliminar ese enlace siempre que sea posible (ya sea en dealloc o viewWillDisappear: o en ambos).
Una cosa rápida para probar es ejecutar el analizador estático Clang . Esto encontrará algunos, pero no todos, problemas en su código que podría estar perdiendo. Comprueba el código en tiempo de compilación, por lo que no es infalible, pero seguramente encontrará la mayoría de los problemas evidentes.
Aquí hay un resumen de lo que aprendí (gracias a algunas excelentes respuestas y comentarios):
- La asignación de objetos NO es lo mismo que el uso de memoria. La respuesta a mi pregunta sobre el elemento net bytes de ObjectAlloc es que no debes prestarle atención, al menos no al determinar problemas con la cantidad de memoria que estás utilizando o qué está causando su bloqueo. No refleja el verdadero uso de la memoria de su aplicación.
- Mi estimación adivina es que ObjectAlloc solo te muestra la memoria tomada por el objeto directo en sí. Entonces, si tiene UIImageView, solo se requieren unos pocos bytes para almacenar las diversas propiedades, pero podría estar apuntando a que una imagen en la memoria ocupa mucho espacio. Por lo tanto, mirar ObjectAlloc es útil solo para asegurarse de que no está creando ni guardando objetos, no le dará una idea de cuánta memoria está usando o cuánto puede usar antes de fallar.
- MemoryMonitor le dará el uso total de la memoria. Puede limitarlo a ver solo el uso de su aplicación utilizando la herramienta de búsqueda en la parte inferior derecha de la ventana Instrumentos.
- Tanto ObjectAlloc como el Monitor de memoria (así como también la herramienta Fugas) son complementos para instrumentos, solo en caso de que eso no sea obvio para otra persona. Puede ejecutar Instruments desde XCode haciendo Run -> Start with Performance Tool. Una vez dentro de Instruments, puede abrir la Biblioteca y agregar nuevos complementos para monitorear diferentes aspectos del rendimiento.
Una cosa a buscar es referencias circulares.
(No quiero que esto suene condescendiente, solo quiero asegurarme de ser claro :) Si el objeto a se refiere al objeto b y el objeto b se refiere al objeto a , es posible que no haya una "filtración" informada porque todos los aún se hace referencia a la memoria, pero puede tratarse de una isla de objetos huérfanos, separada de la aplicación y nunca recuperable. Por supuesto, puede involucrar más objetos ( a se refiere a b , b se refiere a c , c se refiere a a , etc.).
Si está construyendo un gráfico de objetos en alguna parte, y hay referencias atrás o cruzadas, asegúrese de romper los círculos si suelta la raíz (hay diferentes formas de hacerlo. Lo más simple es probablemente asegurarse de que cada clase en cuestión tiene un método releaseAll, o similar, que llama a releaseAll en sus objetos secundarios, luego libera los objetos secundarios, pero esta no siempre es la mejor solución).