Menu
Coddy logo textTech

Padrão de Destrutor

Parte da seção Object Oriented Programming do Journey de C da Coddy — lição 13 de 61.

Todo objeto criado com malloc deve eventualmente ser liberado. Assim como escrevemos uma função create_ para lidar com a alocação, escrevemos uma função free_ para lidar com a limpeza. Este é o padrão destrutor.

A percepção fundamental é que a liberação deve ocorrer na ordem inversa da alocação. Se o seu construtor alocou membros internos primeiro e depois a própria struct, seu destrutor deve liberar os membros da struct primeiro e, em seguida, a struct:

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

void free_person(Person *p) {
    if (p == NULL) return;  // Verificação de segurança
    free(p->name);          // Libera o membro interno primeiro
    free(p);                // Depois libera a própria struct
}

A verificação de NULL no início evita falhas se alguém acidentalmente passar um ponteiro inválido. Após liberar a string name interna, liberamos a própria struct. Se liberássemos p primeiro, perderíamos o acesso a p->name e causaríamos um vazamento de memória.

Usar o destrutor é simples:

Person *alice = create_person("Alice", 30);
// ... use alice ...
free_person(alice);  // Limpe ao terminar

Este padrão garante que toda a memória seja liberada adequadamente. Sem ele, cada objeto que você criar causaria vazamento de memória até que seu programa ficasse sem ela.

challenge icon

Desafio

Fácil

Vamos construir um módulo Movie que demonstra o ciclo de vida completo de um objeto — tanto a criação quanto a destruição. Você praticará a escrita de uma função destruidora que limpa adequadamente toda a memória alocada na ordem correta.

Você criará três arquivos:

  • movie.h: Declare uma struct Movie com dois membros: char *title (uma string alocada dinamicamente) e int year. Declare tanto um construtor create_movie que recebe um título e um ano, quanto um destruidor free_movie que recebe um ponteiro para Movie. Use include guards com o símbolo MOVIE_H.
  • movie.c: Implemente ambas as funções. Seu construtor deve alocar memória para a struct e para sua string de título (não se esqueça do terminador nulo). Seu destruidor deve liberar a memória na ordem inversa da alocação — primeiro a string interna title, depois a própria struct. Inclua uma verificação de NULL no início do seu destruidor por segurança.
  • main.c: Crie um filme, exiba suas informações e, em seguida, limpe adequadamente a memória.

Você receberá duas entradas: o título do filme (uma string) e o ano de lançamento (um inteiro).

No seu arquivo principal, use create_movie para criar um novo filme, imprima suas informações e, em seguida, chame free_movie para liberar toda a memória. Após a liberação, imprima uma mensagem de confirmação.

Imprima a saída neste formato:

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

Por exemplo, com as entradas Inception e 2010, a saída seria:

Movie: Inception (2010)
Memory freed

Lembre-se: a chave para um destruidor adequado é liberar na ordem inversa. O que seu construtor aloca primeiro é liberado por último, e o que ele aloca por último é liberado primeiro.

Folha de consulta

Todo objeto criado com malloc deve ser liberado usando uma função destrutora. Destrutores seguem o padrão de liberar memória na ordem inversa da alocação.

Estrutura básica de um destrutor:

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

void free_person(Person *p) {
    if (p == NULL) return;  // Verificação de segurança
    free(p->name);          // Libera os membros internos primeiro
    free(p);                // Depois libera a própria struct
}

Princípios fundamentais:

  • Sempre inclua uma verificação de NULL no início para evitar falhas
  • Libere os membros internos antes de liberar a própria struct
  • Se você liberar a struct primeiro, perderá o acesso aos seus membros e causará vazamentos de memória

Exemplo de uso:

Person *alice = create_person("Alice", 30);
// ... use alice ...
free_person(alice);  // Limpa ao terminar

Experimente você mesmo

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

int main() {
    char title[100];
    int year;
    
    // Ler entrada
    scanf("%[^\n]", title);
    scanf("%d", &year);
    
    // TODO: Criar um filme usando create_movie
    
    // TODO: Imprimir as informações do filme no formato:
    // Movie: {title} ({year})
    
    // TODO: Liberar o filme usando free_movie
    
    // TODO: Imprimir "Memory freed"
    
    return 0;
}
quiz iconTeste seus conhecimentos

Esta lição inclui um quiz rápido. Comece a lição para respondê-lo e acompanhar seu progresso.

Todas as lições de Object Oriented Programming