Malloc (WIP)
Published May 8, 2025
Cuando escribimos programas, a menudo no sabemos cuánta memoria necesitaremos hasta que el programa esté en ejecución. En estos casos entra en juego malloc
, una función del lenguaje C que permite reservar memoria de forma dinámica durante la ejecución del programa.
Pero antes de ver cómo funciona malloc
, es importante comprender cómo se organiza la memoria en un programa.
🧱 ¿Cómo organiza la memoria el sistema operativo?
Cuando se ejecuta un programa, el sistema operativo le asigna un bloque de memoria. Este bloque no es un único espacio continuo y desordenado, sino que está dividido en regiones bien definidas, cada una con una función específica.
Conocer estas regiones es esencial para entender el funcionamiento de punteros, errores como segmentation fault, o el uso correcto de malloc
.
Las principales regiones son:
1. Segmento de código (text segment)
Contiene las instrucciones del programa. Es de solo lectura para evitar modificaciones accidentales durante la ejecución.
2. Segmento de datos inicializados (data segment)
Almacena variables globales o estáticas que han sido inicializadas con un valor.
🧪 Ejemplo:
int x = 5; // Si x es global o static
3. Segmento BSS (datos no inicializados)
Contiene variables globales o estáticas sin valor inicial asignado.
🧪 Ejemplo:
static int contador; // No inicializada
4. Pila (stack)
Esta región se utiliza para:
- Variables locales
- Parámetros de funciones
- Direcciones de retorno
El stack crece hacia direcciones de memoria más bajas. Cada vez que se llama a una función, se reserva espacio en la pila. Al finalizar, ese espacio se libera automáticamente.
5. Montículo (heap)
Es la región utilizada para reserva dinámica de memoria, como cuando se emplea malloc
.
A diferencia del stack, el heap no se libera automáticamente. El programador debe liberar manualmente la memoria utilizando free()
.
No hacerlo puede provocar fugas de memoria (memory leaks), que degradan el rendimiento del programa.
📊 Esquema visual de la memoria
+-------------------------+ ← Dirección más baja
| Código |
+-------------------------+
| Datos inicializados |
+-------------------------+
| Datos no inicializados |
+-------------------------+
| |
| Heap | ← Crece hacia arriba
| |
| (malloc, etc.) |
+-------------------------+
| |
| Stack | ← Crece hacia abajo
| |
+-------------------------+ ← Dirección más alta
🛠️ Conceptos previos: sbrk
, mmap
y el heap
🔧 ¿Qué es sbrk
?
sbrk
es una función antigua que permite ajustar manualmente el tamaño del heap. Aunque hoy en día no se recomienda en entornos modernos, es útil para comprender cómo se gestionaba la memoria en versiones anteriores de Unix o para implementar un malloc
básico propio.
🧪 Ejemplo:
void* actual = sbrk(0); // Muestra el final actual del heap
sbrk(1024); // Solicita 1024 bytes adicionales
sbrk(-512); // Libera 512 bytes (riesgoso)
📌 Consideraciones:
- ❌ No es segura en programas multihilo.
- ❌ No es portable ni moderna; se usa solo con fines educativos.
- Si falla, devuelve
(void *)-1
.
🧠 ¿Qué es mmap
?
mmap
es una función más moderna y versátil que permite al sistema operativo asignar bloques de memoria, ya sea desde archivos o desde la memoria virtual.
Actualmente, muchas implementaciones de malloc
utilizan internamente mmap
, especialmente para asignaciones grandes. Para bloques pequeños, se puede seguir utilizando sbrk
.
La estrategia depende del sistema operativo y del tamaño de la solicitud.
Como programador, no es necesario preocuparse por cuál se usa internamente: basta con utilizar malloc
, y el sistema se encargará de la gestión.