¿Cómo depurar pérdidas de memoria cuando el instrumento Leaks no las muestra?
Tengo una aplicación de iOS escrita en Swift que está perdiendo memoria; en determinadas situaciones, algunos objetos deberían liberarse, pero no es así. Aprendí sobre el problema simplemente agregando deinit
mensajes de depuración como este:
deinit {
println("DEINIT: KeysProvider released")
}
Por lo tanto, el mensaje deinit debería estar presente en la consola después de tales eventos que deberían provocar la liberación del objeto. Sin embargo, para algunos de los objetos que deberían liberarse, falta el mensaje. Aún así, Leaks Developer Tool no muestra ninguna fuga. ¿Cómo soluciono tal situación?
En Xcode 8, puede hacer clic en el botón "Depurar gráfico de memoria", en la barra de herramientas de depuración (que se muestra en la parte inferior de la pantalla):
Consulte Diagnóstico y resolución de errores de Apple en su aplicación en ejecución: visualizar y diagnosticar el aumento del uso de memoria .
Simplemente identifique el objeto en el panel izquierdo que cree que debería haberse desasignado y le mostrará el gráfico de objetos (que se muestra en el lienzo principal, arriba). Esto es muy útil para identificar rápidamente dónde se establecieron las fuertes referencias en el objeto en cuestión. Desde aquí, puede comenzar su investigación, diagnosticando por qué esas referencias fuertes no se resolvieron (por ejemplo, si el objeto en cuestión tiene una referencia fuerte de otra cosa que debería haber sido desasignada, mire también el gráfico de ese objeto y puede encontrar la problema (por ejemplo, ciclos de referencia fuertes, temporizadores repetidos, etc.).
Observe que en el panel derecho veo el árbol de llamadas. Lo obtuve activando la opción de registro "malloc stack" en la configuración del esquema:
De todos modos, una vez hecho esto, se puede hacer clic en la flecha junto a la llamada al método relevante que se muestra en el seguimiento de la pila en el panel derecho de la primera captura de pantalla de arriba, y se puede ver dónde se estableció originalmente esa fuerte referencia:
La técnica tradicional de Instrumentos (especialmente útil si usa versiones anteriores de Xcode) se describe a continuación, en mi respuesta original.
Sugeriría utilizar la herramienta "Asignaciones" de Instruments con la función "Recuentos de referencias de registros":
Luego puede ejecutar la aplicación en Instrumentos y luego buscar la clase que sabe que tiene fugas y profundizar haciendo clic en la flecha:
Luego puede profundizar en los detalles y ver el seguimiento de la pila usando el panel "Detalles extendidos" a la derecha:
En ese panel de "Detalles extendidos", concéntrese en su código en negro en lugar de las llamadas al sistema en gris. De todos modos, desde el panel "Detalles extendidos", puedes profundizar en tu código fuente, directamente en Instrumentos::
Para obtener más información y demostraciones sobre el uso de instrumentos para localizar problemas de memoria, consulte:
- Vídeo de la WWDC 2021 Detecta y diagnostica problemas de memoria
- Vídeo de la WWDC 2019 Introducción a los instrumentos
- Vídeo de la WWDC 2018 Análisis profundo de la memoria de iOS
- Vídeo de la WWDC 2013 Cómo solucionar problemas de memoria
- Vídeo de la WWDC 2012 Rendimiento de la aplicación iOS: Memoria
Utilice instrumentos para comprobar si hay fugas y pérdida de memoria debido a memoria retenida pero no perdida. Esta última es memoria no utilizada a la que todavía se apunta. Utilice Generación de marcas (Heapshot) en el instrumento Asignaciones en Instrumentos.
Para saber cómo utilizar Heapshot para encontrar pérdidas de memoria, consulte: blog de bbum
Básicamente, el método consiste en ejecutar la herramienta de asignación de instrumentos, tomar una instantánea, ejecutar una iteración de su código y tomar otra instantánea repitiendo 3 o 4 veces. Esto indicará la memoria que se asigna y no se libera durante las iteraciones.
Para calcular los resultados, divulgue para ver las asignaciones individuales.
Si necesita ver dónde se producen las retenciones, liberaciones y liberaciones automáticas de un objeto, utilice los instrumentos:
Ejecute en instrumentos, en Asignaciones, active "Registrar recuentos de referencia" (para Xcode 5 e inferiores, debe detener la grabación para configurar la opción). Haga que la aplicación se ejecute, detenga la grabación, profundice y podrá ver dónde se produjeron todas las retenciones, liberaciones y liberaciones automáticas.