Un recolector de basura (GC) es un administrador de memoria. Muchos lenguajes de programación tienen un GC incorporado. Esta función asigna y desasigna automáticamente la memoria en un programa. Libera memoria atada y no utilizada que ralentiza su aplicación.
La belleza de un GC es que libera memoria en tu nombre, sin que tengas que hacer nada. Por lo tanto, podría considerarlo una característica tan esencial que esperaría que todos los lenguajes de programación la tuvieran. Lamentablemente, este no es el caso; incluso un lenguaje popular como C puede carecer de un GC.
¿Cómo funciona la asignación de memoria?
Cuando ejecuta un programa en cualquier lenguaje de programación, su sistema operativo reserva un pila de datos en la memoria para ese programa. Este programa posee y ocupa esta pila de datos hasta que completa su ejecución. Si su programa necesita más memoria de la que está disponible, puede asignar dinámicamente más memoria del montón de memoria del sistema operativo.
En programación, una variable representa una ubicación de memoria. Entonces, cuando declara una nueva variable, el lenguaje de programación asigna espacio en la memoria para esta variable. La variable ahora tendrá una dirección de memoria. Hasta que asigne un valor a esta variable, permanecerá sin inicializar y podría contener algún valor basura.
Si un lenguaje de programación le permite declarar una variable sin inicializarla, entonces es una variable dinámica. Esto significa que el valor que asigne a la variable puede cambiar con el tiempo. Sin embargo, la ubicación de memoria de la variable seguirá siendo la misma hasta que la desasignes.
¿Cómo funciona la desasignación de memoria?
La asignación de memoria es un proceso similar para todos los lenguajes de programación. Pero el método correspondiente de desasignación de memoria tiende a diferir. Hay dos tipos de métodos de desasignación de memoria; manual y automático. Un GC realiza una desasignación automática.
Desasignación de memoria sin un recolector de basura
los lenguaje de programación c no utiliza un GC para la desasignación de memoria. Por lo tanto, los programadores de C deben asignar y desasignar memoria manualmente. C permite la asignación de memoria dinámica para cuando no sabe, en tiempo de compilación, cuánta memoria usará en tiempo de ejecución.
La biblioteca estándar (stdlib.h) contiene las funciones que C usa para administrar la asignación de memoria dinámica. Estas funciones incluyen:
- malloc(): asigna un tamaño específico de memoria y devuelve un puntero a esa memoria. Si no hay suficiente memoria disponible en el grupo de memoria del sistema operativo, devuelve nulo.
- free(): desasigna un bloque específico de memoria y lo devuelve al grupo de memoria del sistema operativo.
Ejemplo de programa C
#incluir
#incluirEn tprincipal()
{
En t *ptr; // declarar puntero
En t j; // declarar contador// asignar espacio para 200 enteros
punto = (En t *) malloc(200 * tamaño de(En t));// inserta valores enteros en la memoria asignada
// e imprima cada valor en la consola
por (j = 0; j< 200; j++)
{
ptr[j] = j;
imprimir("%d\t",ptr[j]);
}
// desasignar la memoria previamente asignada
libre(ptr);
devolver0;
}
El código anterior asigna memoria para almacenar 200 valores enteros usando el malloc() función. Utiliza un puntero para acceder a esta ubicación de memoria y almacena 200 valores enteros en ella. El puntero también imprime los datos almacenados en la ubicación de la memoria en la consola. Finalmente, el programa desasigna la memoria previamente asignada usando el libre() función.
Desasignación de memoria con un recolector de basura
Varios lenguajes de programación populares utilizan un GC para la gestión de la memoria. Esto facilita mucho la vida de los programadores que utilizan estos lenguajes. C# y Java son dos lenguajes de programación que usan un GC.
El GC de C#
En el lenguaje de programación c#, un GC gestiona la asignación y desasignación de direcciones de memoria. Por lo tanto, un programador de C# no necesita preocuparse por desasignar un objeto después de que complete su propósito.
El GC de C# inicializa un grupo de memoria, llamado montón administrado, para cada nuevo proceso (o programa). llama al VirtualAlloc() función para asignar memoria y la VirtualFree() función para desasignarlo. La mejor parte es que todo esto sucede en segundo plano sin que usted, el programador, haga ningún esfuerzo.
C# GC tiene un motor de optimización, que utiliza para decidir cuándo desasignar memoria. El motor de optimización examina la raíz de la aplicación para determinar qué objetos ya no están en uso. Lo hace creando un gráfico que se extiende desde la raíz de la aplicación hasta los objetos conectados. Esta raíz incluye campos estáticos, variables locales, etc. Cualquier objeto que no esté conectado a la raíz de la aplicación es basura.
El motor de optimización de GC no solo recopila memoria por sí solo. Primero debe haber una nueva solicitud de asignación de memoria. Si el sistema tiene poca memoria disponible, el motor de optimización de GC entrará en juego.
El GC de Java
En Java, un GC también gestiona la asignación y desasignación de direcciones de memoria. Sin embargo, Java actualmente tiene cuatro tipos diferentes de recolectores de basura admitidos:
- Basura primero (G1)
- De serie
- Paralela
- Recolector de basura Z (ZGC)
El recolector de basura G1 es el GC predeterminado de Java desde el lanzamiento de Java Development Kit (JDK) 9. Java organiza los datos en objetos y almacena estos objetos en un montón de tamaño fijo. El recolector de elementos no utilizados G1 divide el almacenamiento dinámico en regiones de almacenamiento dinámico de igual tamaño. Luego dividió estas regiones del montón en dos secciones; jóvenes y viejas generaciones.
Cada vez que crea un nuevo objeto, la asignación de espacio para este objeto ocurre en la generación joven. Usando un proceso de envejecimiento, el recolector de basura G1 copia objetos en las regiones jóvenes a las regiones antiguas. También copia objetos que ya están en la región anterior a una región más antigua.
El recolector de basura G1 luego realiza la mayor parte de su desasignación de memoria en la generación joven, aventurándose ocasionalmente a la sección de generación anterior.
¿Cuáles son los beneficios de tener un recolector de basura?
El beneficio de tener un recolector de basura es que le impide pensar en la administración de la memoria mientras escribe su código. Esto le da tiempo para concentrarse en otros aspectos importantes de su aplicación. Sin embargo, vale la pena destacar varios otros beneficios.
La recuperación de objetos no utilizados y la liberación de memoria proporcionan una ejecución de aplicación más limpia. Si su programa libera memoria lo antes posible, ocupará menos memoria y podrá ejecutarse de manera más eficiente.
La recolección de basura reduce los errores relacionados con la administración de la memoria, como fugas y errores de puntero. Esto se debe a que el proceso ya no depende del programador y su capacidad para escribir código preciso.