Skip to article frontmatterSkip to article content
Site not loading correctly?

This may be due to an incorrect BASE_URL configuration. See the MyST Documentation for reference.

Regla 0x300Fh: Liberá la memoria en el orden inverso a su asignación

Memoria, punteros y tipos (0x30XX)

Universidad Nacional de Río Negro

0x300Fh: Liberá la memoria en el orden inverso a su asignación

Enunciado normativo

La memoria de una estructura anidada DEBE liberarse en el orden inverso al de su asignación: primero los recursos internos (los más profundos) y al final el contenedor que los referencia.

¿Por qué existe esta regla?

El problema

Cuando una estructura contiene punteros a otros bloques —una matriz, una lista, un struct con texto— la liberación va de adentro hacia afuera. Si se libera primero el contenedor, se pierde la única referencia a los bloques internos y se produce una fuga de memoria. El orden inverso refleja las dependencias: el contenedor depende de los elementos y debe vivir al menos tanto como ellos.

Consecuencias de violarla

Tipo de consecuenciaEfecto concreto
Fuga de memoriaLos bloques internos quedan inalcanzables; valgrind los reporta como lost.
Uso de memoria liberadaUn puntero interno se usa después de liberar el contenedor.
EscalabilidadEn un lazo, las fugas acumuladas agotan la memoria del proceso.

Fundamento en el estándar y en la cátedra

C11 §7.22.3.3 exige que cada bloque asignado se libere exactamente una vez; con estructuras anidadas, la única forma es recorrer la jerarquía en orden inverso. La cátedra lo adopta junto con 0x3002h: Liberá siempre la memoria dinámica y asigná NULL al puntero para mitigar punteros colgantes (liberar y anular).

Alcance y excepciones

Aplica a toda estructura con más de un bloque: matrices T **, listas, árboles, structs con punteros a cadenas. No aplica cuando todos los datos viven en un único bloque contiguo: se libera una sola vez y no hay orden que respetar.

Ejemplos exhaustivos

❌ Contraejemplo 1 — Liberar el contenedor antes que los nodos

void lista_destruir(lista_t *lista)
{
    free(lista);
    while (lista->cabeza != NULL)
    {
        nodo_t *siguiente = lista->cabeza->sig;
        free(lista->cabeza);
        lista->cabeza = siguiente;
    }
}

Por qué falla: free(lista) se ejecuta primero y el bucle accede a lista->cabeza después de liberar lista (use-after-free). El contenedor debía sobrevivir hasta terminado el recorrido.

❌ Contraejemplo 2 — Matriz liberada al revés

double **matriz = reservar_matriz(filas, columnas);
free(matriz);
for (size_t i = 0; i < filas; i++)
{
    free(matriz[i]);
}

Por qué falla: se libera el arreglo de punteros antes que las filas. Las filas quedan inalcanzables y el bucle ya no puede acceder a matriz[i]. Cada fila es un bloque perdido. El orden correcto es primero las filas y después el arreglo de punteros.

✅ Ejemplo conforme 1 — Contenedor al final

void lista_destruir(lista_t *lista)
{
    nodo_t *actual = lista->cabeza;
    while (actual != NULL)
    {
        nodo_t *siguiente = actual->sig;
        free(actual);
        actual = siguiente;
    }
    free(lista);
}

Los nodos se liberan primero, conservando el contenedor para recorrerlos; al final se libera el contenedor. Cada bloque conoce a su siguiente antes de liberarse, de modo que no se pierde ninguna dirección.

✅ Ejemplo conforme 2 — Matriz en orden inverso completo

void liberar_matriz(double **matriz, size_t filas)
{
    if (matriz == NULL)
    {
        return;
    }
    for (size_t i = 0; i < filas; i++)
    {
        free(matriz[i]);
    }
    free(matriz);
}

Primero las filas (los recursos internos) y al final el arreglo de punteros. Si la reserva asignó fila por fila, este recorrido reproduce el orden inverso de la asignación. La función tolera NULL y no deja bloques colgados.

⚠️ Casos límite

Cómo detectarla

HerramientaComandoSeñal
gaffgaff check archivo.cLiberación del contenedor antes de sus miembros.
gcc / clanggcc -Wall -Wextra -std=c11 -fanalyzer ...use after 'free' en caminos anidados.
valgrindvalgrind --leak-check=full ./programaindirectly lost / definitely lost de bloque interno.

Checklist de autocontrol

Reglas relacionadas