Gestión Automática (Implícita) de Memoria Dinámica

Introducción

Mientras C y C++ proveen la capacidad de manejar la memoria a través de punteros y las funciones que ya vimos anteriormente, la gran mayoría de los lenguajes modernos se han decidido por la gestión automática o implícita.

En definitiva, la gestión manual se podría pensar como un "metamodelo", o un "modelo de programación", en el cual nosotros, al escribir programas, los tenemos que pensar en base a esas abstracciones (ya vamos a ver en la unidad 2 un poco más de conceptos de abstracciones), es decir en base a punteros, direcciones de memoria. Siempre debo estar pensando si necesito alocar y/o liberar memoria, etc.

Mecanismo

El mecanimo clásico de gestión implícita de memoria es el que se denomina garbage collector (o del castellano recolector de basura).

La idea es que:

    • Durante la ejecución del programa, cuando se crea un nuevo objeto (digo objeto en sentido abstracto. Podría ser un número, un string, un caracter, etc), se va a reservar un sector de memoria para almacenarlo, automáticamente. El programador no necesita saber cuánto espacio ocupa dicho objeto.
    • Estos objetos son referenciados por variables. Que de una forma transparente para nosotros referencian al valor. Sin que sepamos ni podamos acceder a la dirección de memoria ni nada por el estilo.
    • Cuando uno de estos objetos deja de ser referenciado (es decir que no hay ninguna variable activa que lo esté referenciando), pasan a ser detectados por el garbage collector, quien va a liberar el sector de memoria que ocupaban.

Garbage Collector

El garbage collector :

    • es generalmente un subproceso del programa (o la máquina virtual)
    • periódicamente va a estar recorriendo la memoria, y analizando si cada sector tiene referencias o no.
    • Cuando encuentra un sector no referenciado, lo libera.
    • Además se encarga de optimizar el uso de la memoria, especialmente su fragmentación.

Reference Counting

Para que el garbage collector pueda hacer su trabajo, se requiere mantener en forma estricta contadores de referencias para cada sector de memoria. Para eso, colaboran el compilador y el entorno de ejecución.

A nosotros no nos va a importar demasiado cómo es que guardan esas referencias, ni cómo es que colaboran, si no más bien, en qué convenciones se basan para determinar cuándo un objeto está referenciado y cuándo deja de estar referenciado.

Estas convenciones dependen del lenguaje, pero no es nada nuevo.

Un objeto está referenciado si existe una variable activa que apunte a él.

Por ejemplo, si dentro de una función definimos una variable local hora que contiene la hora actual (calculada de alguna forma). Al retornar de esa función como ya sabemos las variables locales dejan de existir.

Pero ojo, la fecha todavía no !

Lo que sucede es que la variable deja de referenciarla. Luego, en algún momento el garbage collector va a detectar a esa fecha como no referenciada y va a liberar su memoria.

A continuación vamos a ver ejemplos con Python para que bajar todo esto a detalle.

Ejemplo de Gestión Implícita en Python

Existen otros lenguajes que, incluso dentro del mismo paradigma estructurado evitan la necesidad de trabajar con la memoria.

Para eso vamos a ver el lenguaje Python, ya que resulta bastante simple sin alejarnos demasiado de lo que ya veníamos viendo, y sin embargo empezar a ver las ventajas de los lenguajes más modernos.

Ver la página Introducción a Python y Manejo de Memoria