Menu
Coddy logo textTech

Patrón Destructor

Parte de la sección Object Oriented Programming del Journey de C de Coddy — lección 13 de 61.

Cada objeto creado con malloc debe ser liberado eventualmente. Al igual que escribimos una función create_ para manejar la asignación, escribimos una función free_ para manejar la limpieza. Este es el patrón destructor.

La idea clave es que la liberación debe ocurrir en orden inverso al de la asignación. Si su constructor asignó primero los miembros internos y luego la propia estructura (struct), su destructor debe liberar primero los miembros de la estructura y luego la estructura misma:

typedef struct {
    char *name;
    int age;
} Person;

void free_person(Person *p) {
    if (p == NULL) return;  // Comprobación de seguridad
    free(p->name);          // Liberar primero el miembro interno
    free(p);                // Luego liberar la estructura misma
}

La comprobación de NULL al inicio evita fallos si alguien pasa accidentalmente un puntero no válido. Después de liberar la cadena interna name, liberamos la estructura en sí. Si liberáramos p primero, perderíamos el acceso a p->name y causaríamos una fuga de memoria.

Usar el destructor es sencillo:

Person *alice = create_person("Alice", 30);
// ... usar alice ...
free_person(alice);  // Limpiar al terminar

Este patrón garantiza que toda la memoria se libere adecuadamente. Sin él, cada objeto que crees tendría fugas de memoria hasta que el programa se quede sin ella.

challenge icon

Desafío

Fácil

Vamos a construir un módulo Movie que demuestre el ciclo de vida completo de un objeto, tanto su creación como su destrucción. Practicarás la escritura de una función destructora que limpie adecuadamente toda la memoria asignada en el orden correcto.

Crearás tres archivos:

  • movie.h: Declara una estructura Movie con dos miembros: char *title (una cadena asignada dinámicamente) e int year. Declara tanto un constructor create_movie que reciba un título y un año, como un destructor free_movie que reciba un puntero a Movie. Utiliza protectores de inclusión (include guards) con el símbolo MOVIE_H.
  • movie.c: Implementa ambas funciones. Tu constructor debe asignar memoria para la estructura y su cadena de título (no olvides el terminador nulo). Tu destructor debe liberar la memoria en el orden inverso a la asignación: primero la cadena interna title, luego la estructura misma. Incluye una comprobación de NULL al inicio de tu destructor por seguridad.
  • main.c: Crea una película, muestra su información y luego limpia adecuadamente la memoria.

Recibirás dos entradas: el título de la película (una cadena) y el año de estreno (un entero).

En tu archivo principal, utiliza create_movie para crear una nueva película, imprime su información y luego llama a free_movie para liberar toda la memoria. Después de liberarla, imprime un mensaje de confirmación.

Imprime la salida en este formato:

Movie: {title} ({year})
Memory freed

Por ejemplo, con las entradas Inception y 2010, la salida sería:

Movie: Inception (2010)
Memory freed

Recuerda: la clave para un destructor adecuado es liberar en orden inverso. Lo que sea que tu constructor asigne primero se libera al final, y lo que asigne al último se libera primero.

Hoja de referencia

Cada objeto creado con malloc debe ser liberado utilizando una función destructora. Los destructores siguen el patrón de liberar memoria en el orden inverso de la asignación.

Estructura básica de un destructor:

typedef struct {
    char *name;
    int age;
} Person;

void free_person(Person *p) {
    if (p == NULL) return;  // Comprobación de seguridad
    free(p->name);          // Liberar primero los miembros internos
    free(p);                // Luego liberar la estructura en sí
}

Principios clave:

  • Incluir siempre una comprobación de NULL al inicio para evitar fallos
  • Liberar los miembros internos antes de liberar la estructura en sí
  • Si liberas la estructura primero, pierdes el acceso a sus miembros y provocas fugas de memoria

Ejemplo de uso:

Person *alice = create_person("Alice", 30);
// ... usar alice ...
free_person(alice);  // Limpiar al terminar

Pruébalo tú mismo

#include <stdio.h>
#include <stdlib.h>
#include "movie.h"

int main() {
    char title[100];
    int year;
    
    // Leer entrada
    scanf("%[^\n]", title);
    scanf("%d", &year);
    
    // TODO: Crear una película usando create_movie
    
    // TODO: Imprimir la información de la película en formato:
    // Movie: {title} ({year})
    
    // TODO: Liberar la película usando free_movie
    
    // TODO: Imprimir "Memory freed"
    
    return 0;
}
quiz iconPonte a prueba

Esta lección incluye un breve cuestionario. Empieza la lección para responderlo y registrar tu progreso.

Todas las lecciones de Object Oriented Programming