In der Programmiersprache C verwaltet der Programmierer den Speicher direkt: Die Zuweisung, Freigabe und Nutzung von Arrays, Strukturen und Zeigern erfolgt manuell. Der Mechanismus der dynamischen Speicherzuweisung existiert in C seit den 1970er Jahren und wird durch spezielle Funktionen der Standardbibliothek (malloc, calloc, realloc, free) realisiert. Dieser Ansatz bietet Leistung und Flexibilität, erfordert jedoch Sorgfalt.
Ein Fehler im Umgang mit Speicher kann zu Lecks, Beschädigung anderer Daten, Abstürzen des Programms oder Sicherheitsanfälligkeiten führen. Oft entsteht ein Fehler durch vergessene free-Aufrufe, ein Überlaufen der Array-Grenzen, falsche Typumwandlungen von Zeigern oder doppelte Speicherfreigaben. Bei Strukturen ist die Situation ähnlich, allerdings besteht auch das Risiko, vergessene dynamische Felder zu löschen.
Um Fehler zu minimieren, wird empfohlen, einen streng strukturierten Code zu entwickeln, alle Speicherzuweisungen und -freigaben zu verfolgen, freigegebene Zeiger nicht zu verwenden und die Größe der zugewiesenen Arrays zu überwachen. Es ist wichtig, statische Analysewerkzeuge und Endprüfungen (valgrind, Sanitizers) zu verwenden sowie sich an Absprachen zu halten: Wer malloc aufgerufen hat, der gibt auch den Speicher frei.
Beispielcode:
#include <stdio.h> #include <stdlib.h> typedef struct { int *arr; size_t size; } ArrayWrapper; ArrayWrapper *create(size_t n) { ArrayWrapper *aw = malloc(sizeof(ArrayWrapper)); if (!aw) return NULL; aw->arr = malloc(sizeof(int) * n); if (!aw->arr) { free(aw); return NULL; } aw->size = n; return aw; } void destroy(ArrayWrapper *aw) { if (aw) { free(aw->arr); free(aw); } }
Schlüsselmerkmale:
Was passiert bei der Freigabe von Speicher an einen Nullzeiger (free(NULL))?
Entsprechend dem C-Standard ist der Aufruf von free auf einen Nullzeiger sicher – es passiert nichts, und es tritt kein Fehler auf. Dies ist bequem, um die Verantwortung für die Speicherfreigabe zu übertragen.
Kann man Speicher nach einem free-Aufruf weiterhin nutzen?
Nein, die Nutzung von Speicher nach der Freigabe (use-after-free) ist ein klassischer Fehler. Die Daten können sich ändern oder der Bereich kann einem anderen Prozess zugewiesen werden. Man sollte den Zeiger immer nach free auf null setzen.
int *ptr = malloc(10); free(ptr); ptr = NULL; // Sicher
Ist es zwingend erforderlich, allen zugewiesenen Speicher vor dem Verlassen des Programms freizugeben?
Technisch gesehen ist es nicht zwingend erforderlich – beim Programmabschluss gibt das Betriebssystem alle Ressourcen frei. Aber das Ignorieren der Speicherfreigabe ist ein Antipattern, das das Debugging erschwert und zu Fehlern in großen, langfristig laufenden Programmen führt.
Ein Entwickler erstellt dynamische Arrays innerhalb einer Funktion und vergisst, sie zu bereinigen:
Vorteile:
Nachteile:
Der gesamte Code wird durch einen statischen Analyzer überprüft, alle Zeiger werden nach free auf null gesetzt, jeder malloc ist mit einem free verbunden:
Vorteile:
Nachteile: