UC3M

Grado en Ing. Telemática/Sist. Audiovisuales/Sist. de Comunicaciones

Arquitectura de Sistemas

Septiembre 2017 - Enero 2018

6.10. Anomalías en la gestión de memoria en C

La gestión de memoria en C se describe como explícita porque tanto las operaciones de reserva como las de liberación han de aparecer explícitamente en el código. En otros lenguajes de programación, como por ejemplo Java, el entorno de ejecución se encarga de recuperar aquellas porciones de memoria que ya no se utilizan, liberando al programador de escribir este código. De la gestión explícita de memoria se derivan varias posibles anomalías cuando fragmentos de memoria no se pueden liberar porque se ha perdido cualquier referencia a ellos. Es lo que se conoce como fuga de memoria. Esa porción de memoria permanece reservada pero inaccesible para el resto de la ejecución de un programa.

6.10.1. La trastienda de la gestión de memoria

Al comenzar la ejecución de un programa, su memoria se divide en tres zonas: la pila, memoria global y el heap. El heap se utiliza para la reserva y liberación de porciones de memoria durante la ejecución del programa. Pero ¿cómo se gestiona esta memoria?

El sistema operativo mantiene una tabla interna en la que apunta qué fragmentos del heap están ocupados y qué punteros se han devuelto como resultado de la petición de reserva. Cuando un programa ejecuta la función malloc para pedir un nuevo fragmento, el sistema busca una porción del tamaño solicitado, si existe devuelve su dirección de comienzo, y se apunta ese bloque como ocupado. De manera análoga, cuando se llama a la función free para liberar un fragmento, el sistema busca en la tabla ese fragmento (que debe estar apuntado previamente como reservado) y libera el espacio para usos futuros. En la siguiente figura se ilustra este funcionamiento.

A la petición de reserva de una porción de 2048 bytes, el gestor de memoria responde con la dirección de un bloque que previamente marca como ocupado. La llamada a free es análoga, pero se recibe una dirección de memoria de un bloque previamente reservado, se busca en la tabla, y si existe, se marca de nuevo como disponible.

Este esquema de gestión de memoria hace que los programas deban ceñirse a unas pautas muy concretas para garantizar el correcto uso de la memoria y sacar el mayor rendimiento a un programa. Por ejemplo, si un programa utiliza una cantidad muy alta de datos dinámicos (esto es, que se almacenan en la memoria solicitada al gestor mediante malloc) y no libera esa memora en cuanto puede, corre el riesgo de agotar la memoria y no terminar la ejecución.