Cómo funciona malloc
El heap y las listas libres
Cómo funciona malloc es una lección gratuita de C Academy en CoddyKit. Esta es la lección 1 de 4. Puedes leer la lección completa abajo gratuitamente — luego la practicas en el navegador con un editor de código integrado y un tutor de IA 24/7. Forma parte de la ruta de aprendizaje de C Academy, y tu progreso se sincroniza en la web y la app de CoddyKit. El curso de C Academy incluye 4 lecciones en total.
Qué hace realmente malloc
Cuando llama a malloc(n), la biblioteca de C le proporciona un puntero a, como mínimo, n bytes utilizables. Sin embargo, el montón es simplemente una región de la memoria del proceso que el asignador gestiona en su nombre.
La tarea del asignador es llevar el control: registrar qué bytes están en uso, cuáles están libres y cómo reutilizar eficientemente la memoria liberada.
El montón procede del sistema operativo
El asignador no crea memoria de la nada. Solicita grandes bloques al sistema operativo mediante llamadas al sistema como brk/sbrk o mmap.
Después divide esos bloques en bloques más pequeños para sus llamadas a malloc. Solicitar memoria al sistema operativo es costoso, por lo que los asignadores la solicitan en grandes cantidades y la reciclan.
/* Conceptual: grow the heap by 4096 bytes */
void *base = sbrk(4096);
if (base == (void *)-1) {
/* out of memory */
}sbrk y el límite del programa
sbrk(n) desplaza el «límite del programa» n bytes hacia arriba y devuelve el límite anterior. La región que acaba de quedar expuesta pasa a estar disponible como espacio del montón.
Es lineal y sencillo, pero no puede devolver fácilmente memoria situada en el medio. Los asignadores modernos prefieren mmap para las solicitudes grandes.
void *prev_break = sbrk(0); /* current break */
sbrk(1024); /* grow by 1 KB */
/* prev_break now points to fresh memory */Metadatos del bloque
Para cada asignación, el asignador almacena una pequeña cabecera junto a los datos: su tamaño y si está libre. Esta cabecera permite que free funcione únicamente con el puntero a los datos que usted devuelve.
El puntero que recibe de malloc apunta después de la cabecera, por lo que los metadatos permanecen ocultos.
typedef struct block {
size_t size;
int free;
struct block *next;
} block_t;Puntero justo después de la cabecera
Un método habitual es la aritmética de punteros: el puntero del usuario es header + 1. Dado un puntero del usuario, la cabecera se encuentra un block_t antes.
Así es como free(p) recupera el tamaño del bloque que asignó, sin que tenga que proporcionárselo.
block_t *hdr = (block_t *)user_ptr - 1;
printf("block size = %zu\n", hdr->size);Demostración de una disposición de cabecera pequeña
Vamos a colocar una cabecera sobre un búfer estático y a leerla de nuevo. Esto muestra cómo un asignador real divide una región en cabecera y carga útil.
No intervienen llamadas al sistema operativo, por lo que se ejecuta en cualquier entorno.
#include <stdio.h>
#include <stddef.h>
typedef struct { size_t size; int free; } block_t;
static char buffer[256];
int main(void) {
block_t *h = (block_t *)buffer;
h->size = 64;
h->free = 0;
void *payload = (char *)buffer + sizeof(block_t);
printf("header bytes = %zu\n", sizeof(block_t));
printf("payload offset = %ld\n", (long)((char *)payload - buffer));
printf("size field = %zu\n", h->size);
return 0;
}La idea de la lista libre
Muchos asignadores enlazan los bloques libres en una lista enlazada. Cuando llama a malloc, el asignador recorre esta lista en busca de un bloque suficientemente grande.
Cuando llama a free, el bloque se marca como libre y se devuelve a la lista para reutilizarlo más adelante, evitando otra solicitud al sistema operativo.
block_t *find_free(block_t *head, size_t size) {
block_t *b = head;
while (b && !(b->free && b->size >= size))
b = b->next;
return b;
}Qué debe hacer free
free(p) encuentra la cabecera de p, la marca como libre e, idealmente, la combina con los bloques libres adyacentes (coalescencia) para combatir la fragmentación.
Llamar dos veces a free con el mismo puntero o liberar un puntero que no pertenece al montón provoca un comportamiento indefinido, porque los metadatos se corrompen.
void my_free(void *p) {
if (!p) return;
block_t *hdr = (block_t *)p - 1;
hdr->free = 1;
/* real allocators coalesce neighbors here */
}Fragmentación
Con el tiempo, liberar y asignar bloques de distintos tamaños deja huecos. La fragmentación externa significa que existe memoria libre, pero está dispersa en fragmentos demasiado pequeños para satisfacer una solicitud.
La fragmentación interna es espacio desperdiciado dentro de un bloque más grande de lo necesario, a menudo debido a la alineación o al redondeo.
Requisitos de alineación
malloc debe devolver memoria alineada para cualquier tipo. En la mayoría de los sistemas de 64 bits, esto significa una alineación de 16 bytes, suficiente para max_align_t.
Los punteros desalineados pueden provocar errores en algunas CPU o ralentizar el acceso en otras, por lo que los asignadores siempre redondean las cargas útiles hasta un límite de alineación.
#include <stdalign.h>
/* alignof(max_align_t) is the strictest required alignment */
size_t a = alignof(max_align_t);Cómo encaja todo
Por tanto, un asignador mínimo necesita: una fuente de memoria (un búfer estático, sbrk o mmap), cabeceras para cada bloque, una estrategia para encontrar espacio libre y gestión de la alineación.
En las próximas lecciones construiremos estas piezas: primero un asignador bump, después listas libres y, por último, la alineación y la división de bloques.
/* The four pillars of a custom allocator */
/* 1. memory source 2. block headers */
/* 3. free-block search 4. alignment */Comprobación rápida
Compruebe su comprensión de los componentes internos de un asignador.
Resumen
malloc gestiona un montón obtenido del sistema operativo mediante sbrk o mmap y lo divide en bloques con cabeceras ocultas que registran el tamaño y el estado de liberación.
Las listas libres permiten reutilizar la memoria, la alineación hace que sea válida para cualquier tipo y la fragmentación es el desafío central. Estas ideas impulsan el asignador que construiremos a continuación.
Preguntas frecuentes
¿La lección «Cómo funciona malloc» es gratis?
Sí — el texto completo de «Cómo funciona malloc» es gratis para leer aquí en la web. Para practicarla de forma interactiva (editor de código integrado y tutor de IA 24/7) y desbloquear el resto del curso de C Academy, actualiza a CoddyKit PRO. El curso de C Academy incluye 4 lecciones en total.
¿Qué aprenderé en «Cómo funciona malloc»?
El heap y las listas libres Practicas C Academy con código real que ejecutas directamente en el navegador, y un tutor de IA 24/7 responde tus preguntas mientras trabajas en la lección.
¿Necesito experiencia previa para empezar C Academy?
No se requiere experiencia previa. C Academy en CoddyKit está estructurado para principiantes hasta estudiantes avanzados, así que puedes empezar aquí o desde el inicio y avanzar a tu ritmo. Esta es la lección 1 de 4.
¿Cuánto tiempo toma la lección «Cómo funciona malloc»?
La mayoría de las lecciones de CoddyKit toman alrededor de 5–10 minutos. Cada una es compacta e interactiva, así que avanzas constantemente y retomas exactamente por donde dejaste en la web y la app.
¿Puedo escribir y ejecutar código en esta lección de C Academy?
Sí. Cada lección de C Academy incluye un editor de código integrado, así que escribes y ejecutas código real directamente en tu navegador y obtienes retroalimentación instantánea de IA — sin configuración local necesaria.
Todas las lecciones de este curso
- Cómo funciona malloc
- Un asignador bump sencillo
- Listas libres y reutilización
- Alineación y división