Dynamische Speicherverwaltung in C: malloc(), calloc()

โšก Intelligente Zusammenfassung

Die dynamische Speicherverwaltung in C reserviert und gibt Heap-Speicher zur Laufzeit mithilfe der Funktionen malloc(), calloc(), realloc() und free() aus der Bibliothek stdlib.h frei, wodurch Programme Arrays und Strukturen flexibel dimensionieren kรถnnen, wenn die Anforderungen vor der Ausfรผhrung unbekannt sind.

  • ๐Ÿง  Stack vs. Heap: Basisvariablen nutzen den automatischen Stack, wรคhrend der dynamische Speicher auf dem Heap liegt und manuell รผber Zeiger verwaltet wird.
  • ๐Ÿ“ฆ malloc(): Reserviert einen nicht initialisierten Block der angeforderten Byte-GrรถรŸe und gibt einen Void-Pointer zurรผck oder NULL, wenn der Speicher nicht ausreicht.
  • ๐Ÿ”ข calloc (): Allokiert mehrere Blรถcke fรผr Arrays, setzt jedes Byte auf Null und gibt einen Zeiger auf den ersten Block zurรผck.
  • ๐Ÿ”„ realloc(): Verรคndert die GrรถรŸe eines vorhandenen Blocks nach oben oder unten, wobei der ursprรผngliche Inhalt an einer mรถglicherweise neuen Position erhalten bleibt.
  • รฐลธยงยน kostenlos(): Gibt Speicher an den Heap zurรผck; jedes malloc() oder calloc() benรถtigt ein entsprechendes free(), um Speicherlecks zu vermeiden.
  • ๐Ÿค– KI-Hilfe: KI-Assistenten und GitHub Copilot entwerfen Code fรผr die Speicherzuweisung und kennzeichnen fehlende free()-Aufrufe und Speicherlecks.

Dynamische Speicherzuweisung in C

Wie funktioniert die Speicherverwaltung in C?

Wenn Sie eine Variable mit einem Basisdatentyp deklarieren, reserviert der C-Compiler automatisch Speicherplatz fรผr die Variable in einem Speicherbereich, der als Stack bezeichnet wird.

Eine Gleitkommazahl belegt beispielsweise typischerweise 4 Byte (plattformabhรคngig), wenn sie deklariert wird. Diese Information lรคsst sich mit dem sizeof-Operator รผberprรผfen, wie im folgenden Beispiel gezeigt.

#include <stdio.h>
int main() { float x; printf("The size of float is %d bytes", sizeof(x)); return 0;}

Der Ausgang wird:

 The size of float is 4 bytes

AuรŸerdem wird ein Array mit einer bestimmten GrรถรŸe in zusammenhรคngenden Speicherblรถcken zugewiesen, wobei jeder Block die GrรถรŸe fรผr ein Element hat:

#include <stdio.h>
int main() { float arr[10];
printf("The size of the float array with 10 element is %d", sizeof(arr)); return 0;}

Das Ergebnis ist:

 The size of the float array with 10 element is 40

Wie bisher gelernt, wird der Speicher bei der Deklaration eines Basisdatentyps oder eines Arrays automatisch verwaltet. In C gibt es jedoch ein Verfahren zur Speicherallokation, das es Ihnen ermรถglicht, ein Programm zu implementieren, bei dem die ArraygrรถรŸe erst zur Laufzeit festgelegt wird. Dieses Verfahren wird als โ€ždynamische Speicherallokationโ€œ bezeichnet.

Dynamische Speicherzuweisung in C

Die dynamische Speicherverwaltung ermรถglicht das manuelle Zuweisen und Freigeben von Speicher entsprechend den Programmieranforderungen. Dynamischer Speicher wird mithilfe von Zeigern verwaltet, die auf den neu zugewiesenen Speicherbereich im sogenannten Heap verweisen.

Jetzt kรถnnen Sie zur Laufzeit problemlos ein Array von Elementen dynamisch erstellen und zerstรถren. Zusammenfassend lรคsst sich sagen, dass die automatische Speicherverwaltung den Stack und die C Dynamic Memory Allocation den Heap verwendet.

Der Die Bibliothek verfรผgt รผber Funktionen, die fรผr die dynamische Speicherverwaltung verantwortlich sind.

Funktion Zweck
malloc () Reserviert den Speicher der angeforderten GrรถรŸe und gibt den Zeiger auf das erste Byte von zurรผck
zugewiesener Platz.
calloc() Weist den Platz fรผr Elemente eines Arrays zu. Initialisiert die Elemente auf Null und gibt einen Zeiger auf den Speicher zurรผck.
realloc() Es wird verwendet, um die GrรถรŸe des zuvor zugewiesenen Speicherplatzes zu รคndern.
Frei() Gibt den zuvor zugewiesenen Speicherplatz frei oder leert ihn.

Lassen Sie uns die oben genannten Funktionen und ihre Anwendung besprechen

malloc()-Funktion in C

Die C-Funktion malloc() steht fรผr Speicherzuweisung. Es handelt sich um eine Funktion, die zur dynamischen Zuweisung eines Speicherblocks verwendet wird. Es reserviert Speicherplatz der angegebenen GrรถรŸe und gibt den Nullzeiger zurรผck, der auf den Speicherort zeigt. Der zurรผckgegebene Zeiger ist normalerweise vom Typ void. Das bedeutet, dass wir jedem Zeiger die Funktion C malloc() zuweisen kรถnnen.

Syntax der Funktion malloc():

ptr = (cast_type *) malloc (byte_size);

Dabei steht:

  • ptr ist ein Zeiger auf cast_type.
  • Die C-Funktion malloc() gibt einen Zeiger auf den zugewiesenen Speicher von byte_size zurรผck.

Beispiel fรผr malloc():

Example: ptr = (int *) malloc (50)

Bei erfolgreicher Ausfรผhrung dieser Anweisung wird ein Speicherplatz von 50 Byte reserviert. Die Adresse des ersten Bytes des reservierten Speicherplatzes wird dem Zeiger ptr vom Typ int zugewiesen.

Betrachten Sie ein anderes Beispiel:

#include <stdlib.h>
int main(){
int *ptr;
ptr = malloc(15 * sizeof(*ptr)); /* a block of 15 integers */
    if (ptr != NULL) {
      *(ptr + 5) = 480; /* assign 480 to sixth integer */
      printf("Value of the 6th integer is %d",*(ptr + 5));
    }
}

Ausgang:

Value of the 6th integer is 480

C malloc()-Funktion

  1. Beachten Sie, dass sizeof(*ptr) anstelle von sizeof(int) verwendet wurde, um den Code robuster zu gestalten, falls die *ptr-Deklaration spรคter in einen anderen Datentyp umgewandelt wird.
  2. Die Zuweisung kann fehlschlagen, wenn der Speicher nicht ausreicht. In diesem Fall wird ein NULL-Zeiger zurรผckgegeben. Daher sollten Sie Code einschlieรŸen, um nach einem NULL-Zeiger zu suchen.
  3. Beachten Sie, dass der zugewiesene Speicher zusammenhรคngend ist und als Array behandelt werden kann. Wir kรถnnen Zeigerarithmetik verwenden, um auf die Array-Elemente zuzugreifen, anstatt Klammern [ ] zu verwenden. Wir empfehlen, + zu verwenden, um auf Array-Elemente zu verweisen, da die Verwendung der Inkrementierung ++ oder += die im Array gespeicherte Adresse รคndert. Zeiger.

Die Funktion Malloc() kann auch mit dem Zeichendatentyp sowie komplexen Datentypen wie Strukturen verwendet werden.

free()-Funktion in C

Die Erinnerung an Variablen wird zur Kompilierzeit automatisch freigegeben. Bei der dynamischen Speicherzuweisung mรผssen Sie den Speicher explizit freigeben. Wenn Sie dies nicht tun, kann es zu einem Fehler wegen unzureichendem Arbeitsspeicher kommen.

Die Funktion free() wird in C aufgerufen, um Speicher freizugeben. Indem Sie Speicher in Ihrem Programm freigeben, stellen Sie mehr Speicher fรผr die spรคtere Verwendung zur Verfรผgung.

Beispielsweise:

#include <stdio.h>
int main() {
int* ptr = malloc(10 * sizeof(*ptr));
if (ptr != NULL){
  *(ptr + 2) = 50;
  printf("Value of the 2nd integer is %d",*(ptr + 2));
}
free(ptr);
}

Ausgang:

 Value of the 2nd integer is 50

calloc()-Funktion in C

Die C-Funktion calloc() steht fรผr zusammenhรคngende Zuweisung. Diese Funktion wird verwendet, um mehrere Speicherblรถcke zuzuweisen. Es handelt sich um eine dynamische Speicherzuweisungsfunktion, die verwendet wird, um den Speicher komplexen Datenstrukturen wie Arrays und Strukturen zuzuweisen.

Die Funktion Malloc() wird verwendet, um einen einzelnen Block Speicherplatz zuzuweisen, wรคhrend die Funktion calloc() in C verwendet wird, um mehrere Blรถcke Speicherplatz zuzuweisen. Jeder von der Funktion calloc() zugewiesene Block hat die gleiche GrรถรŸe.

Syntax der Funktion calloc():

ptr = (cast_type *) calloc (n, size);

Die obige Anweisung wird verwendet, um n Speicherblรถcke gleicher GrรถรŸe zuzuweisen.

Nachdem der Speicherplatz zugewiesen wurde, werden alle Bytes auf Null initialisiert.

Zurรผckgegeben wird der Zeiger, der sich aktuell auf dem ersten Byte des allokierten Speicherplatzes befindet.

Immer wenn bei der Zuweisung von Speicherplatz ein Fehler auftritt, beispielsweise aufgrund von Speichermangel, wird ein Nullzeiger zurรผckgegeben.

Beispiel fรผr calloc():

Das folgende Programm berechnet die Summe einer arithmetischen Folge.

#include <stdio.h>
    int main() {
        int i, * ptr, sum = 0;
        ptr = calloc(10, sizeof(int));
        if (ptr == NULL) {
            printf("Error! memory not allocated.");
            exit(0);
        }
        printf("Building and calculating the sequence sum of the first 10 terms \ n ");
        for (i = 0; i < 10; ++i) { * (ptr + i) = i;
            sum += * (ptr + i);
        }
        printf("Sum = %d", sum);
        free(ptr);
        return 0;
    }

Ergebnis:

Building and calculating the sequence sum of the first 10 terms
Sum = 45

calloc() vs. malloc(): Hauptunterschiede

Nachfolgend ist der Hauptunterschied zwischen malloc() vs. calloc() in C:

Die Funktion calloc() ist im Allgemeinen geeigneter und effizienter als die Funktion malloc(). Wรคhrend beide Funktionen zum Zuweisen von Speicherplatz verwendet werden, kann calloc() mehrere Blรถcke gleichzeitig zuordnen. Sie mรผssen nicht jedes Mal einen Speicherblock anfordern. Die Funktion calloc() wird in komplexen Datenstrukturen verwendet, die mehr Speicherplatz erfordern.

Der durch calloc() in C zugewiesene Speicherblock wird immer auf Null initialisiert, wรคhrend er in der Funktion malloc() in C immer einen Mรผllwert enthรคlt.

realloc()-Funktion in C

Mit der C-Funktion `realloc()` lรคsst sich bereits reservierter Speicher vergrรถรŸern. Dabei wird der aktuelle Speicherblock erweitert, wรคhrend der ursprรผngliche Inhalt unverรคndert bleibt. `realloc()` steht in C fรผr โ€žReallocation of Memoryโ€œ (Speicherneuzuweisung).

realloc() kann auch verwendet werden, um die GrรถรŸe des zuvor zugewiesenen Speichers zu reduzieren.

Syntax der realloc()-Funktion:

ptr = realloc (ptr,newsize);

Die obige Anweisung weist einen neuen Speicherplatz mit einer angegebenen GrรถรŸe in der Variablen newsize zu. Nach Ausfรผhrung der Funktion wird der Zeiger auf das erste Byte des Speicherblocks zurรผckgesetzt. Die neue GrรถรŸe kann grรถรŸer oder kleiner als der vorherige Speicher sein. Wir kรถnnen nicht sicher sein, ob der neu zugewiesene Block auf denselben Speicherort verweist wie der vorherige Speicherblock. Diese Funktion kopiert alle vorherigen Daten in die neue Region. Es stellt sicher, dass die Daten sicher bleiben.

Beispiel fรผr realloc():

#include <stdio.h>
int main () {
   char *ptr;
   ptr = (char *) malloc(10);
   strcpy(ptr, "Programming");
   printf(" %s,  Address = %u\n", ptr, ptr);

   ptr = (char *) realloc(ptr, 20); //ptr is reallocated with new size
   strcat(ptr, " In 'C'");
   printf(" %s,  Address = %u\n", ptr, ptr);
   free(ptr);
   return 0;
}

Wenn die Operation von realloc() in C fehlschlรคgt, wird ein Nullzeiger zurรผckgegeben und die vorherigen Daten werden ebenfalls freigegeben.

Dynamische Arrays in C

Ein dynamisches Array in C ermรถglicht es, die Anzahl der Elemente nach Bedarf zu erhรถhen. Dynamische C-Arrays werden hรคufig in Informatikalgorithmen verwendet.

Im folgenden Programm haben wir ein dynamisches Array erstellt und seine GrรถรŸe geรคndert in C

#include <stdio.h>
    int main() {
        int * arr_dynamic = NULL;
        int elements = 2, i;
        arr_dynamic = calloc(elements, sizeof(int)); //Array with 2 integer blocks
        for (i = 0; i < elements; i++) arr_dynamic[i] = i;
        for (i = 0; i < elements; i++) printf("arr_dynamic[%d]=%d\n", i, arr_dynamic[i]);
        elements = 4;
        arr_dynamic = realloc(arr_dynamic, elements * sizeof(int)); //reallocate 4 elements
        printf("After realloc\n");
        for (i = 2; i < elements; i++) arr_dynamic[i] = i;
        for (i = 0; i < elements; i++) printf("arr_dynamic[%d]=%d\n", i, arr_dynamic[i]);
        free(arr_dynamic);
    }

Ergebnis des C Dynamic Array-Programms auf dem Bildschirm:

 
arr_dynamic[0]=0
arr_dynamic[1]=1
After realloc
arr_dynamic[0]=0
arr_dynamic[1]=1
arr_dynamic[2]=2
arr_dynamic[3]=3

Hรคufig gestellte Fragen

Ein Speicherleck entsteht, wenn der von malloc() oder calloc() belegte Heap-Speicher nicht freigegeben wird. Dies lรคsst sich verhindern, indem jeder Speicherbelegung ein entsprechender free()-Aufruf folgt, sobald der Speicherblock nicht mehr benรถtigt wird.

Ein hรคngender Zeiger enthรคlt weiterhin die Adresse des Speichers, den free() bereits freigegeben hat. Das Dereferenzieren dieses Zeigers fรผhrt zu undefiniertem Verhalten. Weisen Sie dem Zeiger daher direkt nach der Freigabe NULL zu, um auf Nummer sicher zu gehen.

Nein. C besitzt keine automatische Speicherbereinigung (Garbage Collector), daher wird der Heap-Speicher nicht automatisch freigegeben. Der Programmierer muss jeden Speicherblock explizit mit `free()` freigeben; andernfalls bleibt die Speicherbelegung bis zum Programmende bestehen.

Nein. Zweimaliges Aufrufen von `free()` auf derselben Adresse fรผhrt zu einem doppelten Freigabevorgang und lรถst undefiniertes Verhalten oder einen Absturz aus. Durch das Setzen des Zeigers auf `NULL` nach dem ersten `free()`-Aufruf wird jeder weitere Aufruf von `free()` unschรคdlich.

realloc(NULL, size) verhรคlt sich genau wie malloc(size) und reserviert einen neuen Speicherblock. realloc(ptr, 0) gibt den Block wieder frei; daher sollte man immer den zurรผckgegebenen Zeiger speichern, anstatt den ursprรผnglichen zu รผberschreiben.

Tools wie Valgrind, AddressSanitizer und Dr. Memory track alle Zuordnungs- und Berichtsblรถcke, die nie freigegeben wurden, zusammen mit der genauen Zeile, helping Sie spรผren Lecks vor der Verรถffentlichung auf.

Ja. Ein KI-Programmierassistent erstellt anhand einer Eingabeaufforderung malloc()-, calloc()- und free()-Sequenzen, erklรคrt Zeigerfehler und markiert fehlende free()-Aufrufe. Kompilieren und testen Sie den generierten Code immer, bevor Sie ihm vertrauen.

GitHub-Copilot schlรคgt Allokationsblรถcke, NULL-Prรผfungen und passende free()-Aufrufe aus einem Kommentar vor; รผberprรผfen Sie jede Vervollstรคndigung auf Speicherlecks und korrekte GrรถรŸen, bevor Sie sie ausliefern.

Fassen Sie diesen Beitrag mit folgenden Worten zusammen: