Articulo de referencia

Basura (informática)

En informática , la basura incluye datos , objetos u otras regiones de la memoria de un sistema informático (u otros recursos del sistema) que no se utilizarán en ningún cálculo...

En informática , la basura incluye datos , objetos u otras regiones de la memoria de un sistema informático (u otros recursos del sistema) que no se utilizarán en ningún cálculo futuro por parte del sistema o de un programa que se ejecute en él. Dado que cada sistema informático tiene una cantidad finita de memoria y la mayoría del software genera basura, con frecuencia es necesario liberar la memoria ocupada por basura y devolverla al montón , o grupo de memoria, para su reutilización.

Clasificación

La basura se clasifica generalmente en dos tipos: basura sintáctica , cualquier objeto o dato que se encuentre dentro del espacio de memoria de un programa pero que sea inaccesible desde el conjunto raíz del programa ; y basura semántica , cualquier objeto o dato al que un programa en ejecución nunca acceda para ninguna combinación de entradas del programa. Se dice que los objetos y datos que no son basura están activos .

En términos sencillos, la basura sintáctica son datos inaccesibles , y la basura semántica son datos a los que no se podrá acceder. Más precisamente, la basura sintáctica son datos inaccesibles debido al grafo de referencias (no existe una ruta hacia ellos), lo cual puede determinarse mediante diversos algoritmos, como se explica en el análisis de la recolección de basura , y solo requiere analizar los datos, no el código. La basura semántica son datos a los que no se podrá acceder, ya sea porque son inaccesibles (y por lo tanto también basura sintáctica), o porque son accesibles pero no se accederá a ellos; determinar esto último requiere análisis de código y, en general, es indecidible .

La basura sintáctica es un subconjunto (generalmente estricto) de la basura semántica, ya que es perfectamente posible que un objeto mantenga una referencia a otro objeto sin haberlo utilizado nunca.

Ejemplo

En la siguiente implementación simple de pila en Java, cada elemento extraído de la pila se convierte en basura semántica una vez que no hay referencias externas a él: [ a ]

clase pública Pila { objeto privado [] elementos ; entero privado tamaño ;public Stack ( int capacity ) { elements = new Object [ capacity ] ; } public void push ( Object e ) { elements [ size ++] = e ; } public Object pop () { return elements [-- size ] ; } }

Esto se debe a que elements[]aún contiene una referencia al objeto, pero este nunca volverá a ser accedido a través de dicha referencia, ya que elements[]es privado de la clase y el popmétodo solo devuelve referencias a elementos que aún no ha eliminado. (Después de decrementar size, esta clase nunca volverá a acceder a ese elemento). Sin embargo, para saber esto se requiere analizar el código de la clase, lo cual, en general, es indecidible.

Si una pushllamada posterior vuelve a aumentar el tamaño de la pila hasta el tamaño anterior, sobrescribiendo esta última referencia, entonces el objeto se convertirá en basura sintáctica, porque nunca más se podrá acceder a él y será susceptible de ser recolectado por el recolector de basura.

Recogida automática de basura

Un ejemplo de la recolección automática de basura sintáctica, mediante la recolección de basura por conteo de referencias , se puede producir utilizando el intérprete de línea de comandos de Python :

>>> clase Foo : ... """Esta es una clase de prueba vacía.""" ... pasar ... >>> bar = Foo () >>> bar <__main__.Foo object at 0x54f30> >>> del bar

En esta sesión, se crea un objeto, se muestra su ubicación en la memoria y, a continuación, se destruye la única referencia al objeto; a partir de este momento, no hay forma de volver a utilizarlo, ya que no existen referencias al mismo. Esto se hace evidente cuando intentamos acceder a la referencia original:

>>> bar Traceback (última llamada): Archivo "<stdin>" , línea 1 , en ? NameError : el nombre 'bar' no está definido

Como ahora es imposible hacer referencia al objeto, este se ha vuelto inútil; es basura. Dado que Python utiliza la recolección de basura, libera automáticamente la memoria que se usaba para el objeto para que pueda volver a utilizarse:

>>> clase Bar : ... """Esta es otra clase de prueba.""" ... pasar ... >>> baz = Bar () >>> baz <__main__.Bar object at 0x54f30>

La instancia Bar ahora reside en la dirección de memoria 0x54f30 , en el mismo lugar donde se encontraba nuestro objeto anterior, la instancia Foo . Dado que la instancia Foo fue destruida, liberando la memoria que la contenía, el intérprete crea el objeto Bar en la misma dirección de memoria que antes, aprovechando así los recursos disponibles.

Efectos

La basura consume memoria del montón, por lo que se desea recolectarla (para minimizar el uso de memoria, permitir una asignación de memoria más rápida y prevenir errores de falta de memoria al reducir la fragmentación del montón y el uso de memoria).

Sin embargo, la recolección de basura lleva tiempo y, si se realiza manualmente, requiere una sobrecarga de programación. Además, la recolección de basura destruye objetos y, por lo tanto, puede provocar llamadas a finalizadores , ejecutando código potencialmente arbitrario en un punto arbitrario de la ejecución del programa. Una recolección de basura incorrecta (liberar memoria que no es basura), principalmente debido a errores en la recolección manual de basura (en lugar de errores en los recolectores de basura), resulta en violaciones de seguridad de memoria (que a menudo crean vulnerabilidades de seguridad) debido al uso de punteros colgantes .

La basura sintáctica se puede recolectar automáticamente, y los recolectores de basura se han estudiado y desarrollado exhaustivamente. La basura semántica generalmente no se puede recolectar automáticamente, lo que provoca fugas de memoria incluso en lenguajes con recolección de basura. La detección y eliminación de basura semántica se realiza normalmente mediante una herramienta de depuración especializada llamada analizador de memoria dinámica (heap profiler) , que permite ver qué objetos están activos y cómo se puede acceder a ellos, lo que posibilita eliminar la referencia no deseada.

Eliminar la basura

El problema de gestionar la desasignación de basura es bien conocido en la informática. Se adoptan varios enfoques:

  • Muchos sistemas operativos recuperan la memoria y los recursos utilizados por un proceso o programa cuando este finaliza. Los programas sencillos o de corta duración, diseñados para ejecutarse en dichos entornos, pueden finalizar y permitir que el sistema operativo realice la recuperación necesaria.
  • En sistemas o lenguajes de programación con gestión manual de memoria , el programador debe configurar explícitamente la liberación de memoria cuando ya no se utilice. C y C++ son dos lenguajes muy conocidos que admiten este modelo.
  • La recolección de basura utiliza diversos algoritmos para analizar automáticamente el estado de un programa, identificar la basura y liberarla sin intervención del programador. Muchos lenguajes de programación modernos, como Java y Haskell, ofrecen recolección de basura automatizada. Sin embargo, no se trata de un desarrollo reciente, ya que también se ha utilizado en lenguajes más antiguos como LISP .
  • Se están realizando investigaciones sobre enfoques basados ​​en la teoría de tipos (como la inferencia de regiones ) para la identificación y eliminación de código basura en un programa. Aún no se ha desarrollado una solución general basada en la teoría de tipos para este problema.

Notas

  1. Simplificado a partir del elemento 6 de Effective Java al omitir el redimensionamiento y las excepciones explícitas.
  • Benjamin Pierce (editor), Temas avanzados en tipos y lenguajes de programación , MIT Press (2005), ISBN 0-262-16228-8
  • Richard Jones y Rafael Lins, Recolección de basura: algoritmos para la gestión automatizada de memoria dinámica , Wiley and Sons (1996), ISBN 0-471-94148-4