Menu
Coddy logo textTech

Destruktor-Muster

Teil des Abschnitts Object Oriented Programming der C-Journey von Coddy — Lektion 13 von 61.

Jedes Objekt, das mit malloc erstellt wurde, muss schließlich freigegeben werden. Genauso wie wir eine create_-Funktion geschrieben haben, um die Allokation zu handhaben, schreiben wir eine free_-Funktion, um das Aufräumen zu handhaben. Dies ist das Destruktor-Muster.

Die entscheidende Erkenntnis ist, dass das Freigeben in umgekehrter Reihenfolge der Allokation erfolgen muss. Wenn Ihr Konstruktor zuerst interne Member und dann das Struct selbst allokiert hat, muss Ihr Destruktor zuerst die Member des Structs und dann das Struct selbst freigeben:

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

void free_person(Person *p) {
    if (p == NULL) return;  // Sicherheitsprüfung
    free(p->name);          // Zuerst internes Element freigeben
    free(p);                // Dann das Struct selbst freigeben
}

Die NULL-Prüfung am Anfang verhindert Abstürze, falls versehentlich ein ungültiger Pointer übergeben wird. Nach dem Freigeben des internen name-Strings geben wir das Struct selbst frei. Wenn wir zuerst p freigeben würden, verlören wir den Zugriff auf p->name und würden ein Speicherleck verursachen.

Die Verwendung des Destruktors ist unkompliziert:

Person *alice = create_person("Alice", 30);
// ... alice verwenden ...
free_person(alice);  // Aufräumen, wenn fertig

Dieses Muster stellt sicher, dass der gesamte Speicher ordnungsgemäß freigegeben wird. Ohne dieses Muster würde jedes von Ihnen erstellte Objekt Speicherlecks verursachen, bis Ihrem Programm der Speicher ausgeht.

challenge icon

Aufgabe

Einfach

Lassen Sie uns ein Movie-Modul erstellen, das den vollständigen Objektlebenszyklus demonstriert – sowohl die Erstellung als auch die Zerstörung. Sie werden üben, eine Destruktor-Funktion zu schreiben, die den gesamten zugewiesenen Speicher ordnungsgemäß in der richtigen Reihenfolge bereinigt.

Sie werden drei Dateien erstellen:

  • movie.h: Deklarieren Sie ein Movie-Struct mit zwei Elementen: char *title (ein dynamisch zugewiesener String) und int year. Deklarieren Sie sowohl einen Konstruktor create_movie, der einen Titel und ein Jahr entgegennimmt, als auch einen Destruktor free_movie, der einen Movie-Pointer entgegennimmt. Verwenden Sie Include-Guards mit dem Symbol MOVIE_H.
  • movie.c: Implementieren Sie beide Funktionen. Ihr Konstruktor sollte Speicher für das Struct und seinen Titel-String reservieren (vergessen Sie nicht den Null-Terminator). Ihr Destruktor muss den Speicher in umgekehrter Reihenfolge der Zuweisung freigeben – zuerst den internen title-String, dann das Struct selbst. Fügen Sie zur Sicherheit eine NULL-Prüfung am Anfang Ihres Destruktors ein.
  • main.c: Erstellen Sie einen Film, zeigen Sie seine Informationen an und bereinigen Sie dann ordnungsgemäß den Speicher.

Sie erhalten zwei Eingaben: den movie title (einen String) und das release year (eine Ganzzahl).

Verwenden Sie in Ihrer Hauptdatei create_movie, um einen neuen Film zu erstellen, geben Sie seine Informationen aus und rufen Sie dann free_movie auf, um den gesamten Speicher freizugeben. Geben Sie nach dem Freigeben eine Bestätigungsmeldung aus.

Geben Sie die Ausgabe in diesem Format aus:

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

Zum Beispiel wäre bei den Eingaben Inception und 2010 die Ausgabe:

Movie: Inception (2010)
Memory freed

Denken Sie daran: Der Schlüssel zu einem ordnungsgemäßen Destruktor ist das Freigeben in umgekehrter Reihenfolge. Was Ihr Konstruktor zuerst reserviert, wird zuletzt freigegeben, und was er zuletzt reserviert, wird zuerst freigegeben.

Spickzettel

Jedes mit malloc erstellte Objekt muss mit einer Destruktor-Funktion freigegeben werden. Destruktoren folgen dem Muster, Speicher in umgekehrter Reihenfolge der Allokation freizugeben.

Grundlegende Destruktor-Struktur:

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

void free_person(Person *p) {
    if (p == NULL) return;  // Sicherheitsprüfung
    free(p->name);          // Zuerst interne Member freigeben
    free(p);                // Dann das Struct selbst freigeben
}

Schlüsselprinzipien:

  • Fügen Sie am Anfang immer eine NULL-Prüfung ein, um Abstürze zu verhindern
  • Geben Sie interne Member frei, bevor Sie das Struct selbst freigeben
  • Wenn Sie zuerst das Struct freigeben, verlieren Sie den Zugriff auf seine Member und verursachen Speicherlecks

Verwendungsbeispiel:

Person *alice = create_person("Alice", 30);
// ... alice verwenden ...
free_person(alice);  // Aufräumen, wenn fertig

Probier es selbst

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

int main() {
    char title[100];
    int year;
    
    // Eingabe lesen
    scanf("%[^\n]", title);
    scanf("%d", &year);
    
    // TODO: Erstelle einen Film mit create_movie
    
    // TODO: Gib die Filminformationen in folgendem Format aus:
    // Movie: {title} ({year})
    
    // TODO: Gib den Film mit free_movie frei
    
    // TODO: Gib "Memory freed" aus
    
    return 0;
}
quiz iconTeste dich selbst

Diese Lektion enthält ein kurzes Quiz. Starte die Lektion, um es zu beantworten und deinen Fortschritt zu speichern.

Alle Lektionen in Object Oriented Programming