objective c - ¿Cuál es la diferencia entre la memoria abandonada y una fuga de memoria?
objective-c ios (3)
La memoria abandonada son las pérdidas de memoria. El Análisis de Headshot te ayudará a encontrar un crecimiento de memoria indeseable. Este es un buen artículo sobre eso. http://www.friday.com/bbum/2010/10/17/when-is-a-leak-not-a-leak-using-heapshot-analysis-to-find-undesirable-memory-growth/
Ambas son exactamente lo mismo, excepto que "memoria abandonada" se refiere a un gráfico de objeto completo filtrado en lugar de a un solo objeto. ¿Derecha?
No estoy seguro de si hay una terminología estándar, pero también existe la posibilidad de tener memoria en torno a la cual tiene una referencia, pero nunca será utilizada. (La función Heap Shot del instrumento Leaks puede ayudar a rastrear esto.) Yo llamo a esto "hinchazón" para distinguirlo de una verdadera fuga. Ambos son desperdicio de memoria.
En primer lugar, debe comprender la noción de "gráfico de objeto de memoria" o "gráfico de objeto de aplicación" (o, simplemente, "gráfico de objeto" tal como se aplica a los búferes asignados). En este caso, "objeto" se refiere a cualquier asignación en su aplicación, ya sea un objeto o un simple buffer malloc()
ed. La parte "gráfico" si es que cualquier objeto puede contener una referencia a - un puntero - a otros objetos.
El "gráfico de objetos vivos" de una aplicación son todas las asignaciones que se pueden alcanzar, directa o indirectamente, desde las diversas "raíces" en la aplicación. Una "raíz" es algo que, por sí solo, representa una referencia en vivo a un objeto, independientemente de si algo más hace referencia explícita a la raíz o no.
Por ejemplo, las variables globales son raíces; al referirse a un objeto, una variable global, por definición, hace que ese objeto sea parte del gráfico de objetos vivos de la aplicación. Y, por implicación, cualquier objeto que el objeto referido por la variable global también se considera vivo; no se filtró.
Lo mismo ocurre con la pila; cualquier objeto al que se haga referencia en la pila viva de cualquier subproceso se considera en sí mismo en vivo.
Con esto en mente, una fuga y memoria abandonada realmente tienen dos significados distintos.
Fuga
Una fuga es una pieza de memoria para la que no hay referencias a la asignación de ningún objeto activo en el gráfico de objetos en vivo de la aplicación .
Es decir, la memoria es inalcanzable y, por lo tanto, no hay forma de que vuelva a referirse a ella (salvo errores). Es un recuerdo muerto.
Tenga en cuenta que si el objeto A apunta al objeto B y el objeto B apunta a A, pero nada en el gráfico del objeto vivo apunta a A o B, sigue siendo una fuga. Si las referencias B-> A y A-> B son referencias retenidas, usted obtuvo un ciclo de retención y una fuga.
Memoria abandonada
Las asignaciones que están en el gráfico de objetos en vivo de la aplicación pero que ya no se pueden alcanzar debido a problemas con la lógica de la aplicación se consideran abandonadas, pero no filtradas.
Por ejemplo, supongamos que tiene un caché cuyas entradas son instancias de NSData
que se descargaron de una URL donde la URL contiene una ID de sesión en la URL (un patrón común) y esa ID de sesión + URL se usa como clave para buscar cosas en el caché Ahora, supongamos que el usuario cierra la sesión y se destruye la ID de la sesión. Si la memoria caché no está también borrada de todas las entradas específicas de esa ID de sesión, todos esos objetos NSData
serán abandonados, pero no se NSData
, ya que aún pueden alcanzarse a través de la memoria caché.
En realidad, hay poco uso para hacer una distinción tan fuerte entre los dos, salvo que esa fijación requiere estrategias muy diferentes.
La solución de una fuga es averiguar de dónde proviene el reten remanente (o dónde podría ser necesario insertar una llamada perdida a free()
, en el caso de una fuga basada en malloc()
). Dado que no se puede llegar a una fuga detectada desde el gráfico de objetos vivos, la reparación de una fuga es realmente así de simple.
Reparar la memoria abandonada puede ser mucho más complicado por un par de razones.
En primer lugar, la memoria aún se puede alcanzar desde el gráfico del objeto vivo. Por lo tanto, por definición, hay un problema algorítmico en su aplicación que mantiene viva la memoria. Encontrar y solucionar eso a menudo puede ser mucho más difícil y potencialmente perjudicial luego de arreglar una mera fuga.
En segundo lugar, podría haber referencias débiles no retenidas a cero a la asignación abandonada. Es decir, si averigua dónde podar las referencias sólidas y hacer que la asignación realmente desaparezca, eso no significa que su trabajo haya terminado; si quedan referencias débiles restantes que no sean zeroing, ahora serán punteros colgantes y ..... BOOM .
Como lo indicó Amit, Heapshot Analysis es bastante hábil para encontrar fugas, memoria abandonada y, bastante importante, "Crecimiento de memoria indeseable".