- La basura también puede referirse a datos confusos; Consulte Corrupción de datos .
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 serán utilizados en ningún cálculo futuro por el sistema o por un programa que se ejecute en él. Debido a que cada sistema informático tiene una cantidad finita de memoria y la mayoría del software produce basura, con frecuencia es necesario desasignar la memoria que está ocupada por la 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 no accesible desde el conjunto raíz del programa ; y basura semántica , cualquier objeto o dato al que nunca accede un programa en ejecución para cualquier combinación de entradas de programa. Se dice que los objetos y datos que no son basura están activos .
En términos casuales, la basura sintáctica son datos a los que no se puede acceder, y la basura semántica son datos a los que no se llega. Más precisamente, la basura sintáctica son datos a los que no se puede acceder debido al gráfico de referencia (no hay una ruta hacia él), que puede ser determinado por muchos algoritmos, como se explica en Seguimiento 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 accederá, ya sea porque es inalcanzable (por lo tanto también basura sintáctica), o es accesible pero no se accederá; esto último requiere un análisis del código y, en general, es un problema indecidible .
La basura sintáctica es un subconjunto (generalmente estricto) de basura semántica, ya que es completamente posible que un objeto tenga una referencia a otro objeto sin usar ese objeto.
Ejemplo
En la siguiente implementación de pila simple 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]
Pila de clase pública { elementos de Objeto privado [] ; tamaño int privado ; Pila pública ( capacidad int ) { elementos = nuevo Objeto [ capacidad ] ; } public void push ( Objeto e ) { elementos [ tamaño ++] = e ; } objeto público pop () { elementos de retorno [- tamaño ] ; } }
Esto se debe a que elements[]
todavía contiene una referencia al objeto, pero nunca se volverá a acceder al objeto a través de esta referencia, porque elements[]
es privado para la clase y el pop
método solo devuelve referencias a elementos que aún no ha aparecido. (Después de que disminuya size
, esta clase nunca volverá a acceder a ese elemento). Sin embargo, saber esto requiere un análisis del código de la clase, que es indecidible en general.
Si una push
llamada posterior vuelve a hacer crecer la pila al tamaño anterior, sobrescribiendo esta última referencia, entonces el objeto se convertirá en basura sintáctica, porque nunca se podrá acceder de nuevo y será elegible para la recolección de basura.
Recolección automática de basura
Se puede producir un ejemplo de la recolección automática de basura sintáctica, mediante el recuento de referencias de la recolección de basura, utilizando el intérprete de línea de comandos de Python :
>>> class Foo : ... "" "Esta es una clase de prueba vacía." "" ... pass ... >>> 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 luego se destruye la única referencia al objeto; no hay forma de volver a usar el objeto a partir de este momento, ya que no hay referencias a él. . Esto se hace evidente cuando intentamos acceder a la referencia original:
>>> barra Traceback (última llamada más reciente): Archivo "" , línea 1 , en ? NameError : el nombre 'bar' no está definido
Como ahora es imposible referirse al objeto, el objeto se ha vuelto inútil; es basura. Dado que Python usa la recolección de basura, automáticamente desasigna la memoria que se usó para el objeto para que pueda usarse nuevamente:
>>> class Bar : ... "" "Esta es otra clase de prueba." "" ... pass ... >>> baz = Bar () >>> baz <__ main__.Bar objeto en 0x54f30>
La instancia de Bar ahora reside en la ubicación de la memoria. 0x54f30 ; en el mismo lugar donde nuestro objeto anterior, el Se localizó una instancia de Foo . Desde el La instancia de Foo fue destruida, liberando la memoria utilizada para contenerla, el intérprete crea el Bloquear el objeto en la misma ubicación de memoria que antes, haciendo un buen uso de los recursos disponibles.
Efectos
La basura consume memoria del montón y, por lo tanto, uno desea recolectarla (para minimizar el uso de la memoria, permitir una asignación de memoria más rápida y evitar errores de memoria insuficiente al reducir la fragmentación del montón y el uso de la memoria).
Sin embargo, la recolección de basura lleva tiempo y, si se hace manualmente, requiere una sobrecarga de codificación. Además, la recolección de basura destruye objetos y, por lo tanto, puede causar llamadas a finalizadores , ejecutando código potencialmente arbitrario en un punto arbitrario en la ejecución del programa. La recolección de basura incorrecta (desasignar memoria que no es basura), principalmente debido a errores en la recolección de basura manual (en lugar de errores en los recolectores de basura), da como resultado violaciones de seguridad de la memoria (que a menudo crean agujeros 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 ampliamente. La basura semántica no se puede recolectar automáticamente en general y, por lo tanto, causa pérdidas de memoria incluso en los lenguajes recolectados de basura. La detección y eliminación de la basura semántica se realiza normalmente mediante una herramienta de depuración especializada llamada heap profiler , que permite ver qué objetos están activos y cómo se puede acceder a ellos, lo que permite eliminar la referencia no deseada.
Eliminando basura
El problema de gestionar la desasignación de basura es bien conocido en informática. Se toman varios enfoques:
- Muchos sistemas operativos recuperan la memoria y los recursos utilizados por un proceso o programa cuando termina. Los programas simples o de corta duración que están diseñados para ejecutarse en dichos entornos pueden salir y permitir que el sistema operativo realice cualquier recuperación necesaria.
- En sistemas o lenguajes de programación con gestión manual de memoria , el programador debe disponer explícitamente que la memoria se desasigne cuando ya no se utilice. C y C ++ son dos lenguajes conocidos que admiten este modelo.
- La recolección de basura utiliza varios algoritmos para analizar automáticamente el estado de un programa, identificar la basura y desasignarla sin la intervención del programador. Muchos lenguajes de programación modernos como Java y Haskell proporcionan recolección de basura automatizada. Sin embargo, no es un desarrollo reciente, ya que también se ha utilizado en lenguajes más antiguos como LISP .
- Hay investigaciones en curso sobre enfoques teóricos de tipos (como la inferencia de regiones ) para la identificación y eliminación de basura de un programa. No se ha desarrollado una solución general de teoría de tipos al problema.
Notas
- ^ Simplificado de Effective Java Item 6 al omitir el cambio de tamaño y las excepciones explícitas.
enlaces externos
- 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, Garbage Collection: Algorithms for Automated Dynamic Memory Management , Wiley and Sons (1996), ISBN 0-471-94148-4