Überprüfung auf Allokationsfehler
Teil des Abschnitts Logic & Flow der C-Journey von Coddy — Lektion 34 von 63.
Während malloc() ein leistungsstarkes Werkzeug für die dynamische Speicherallokation ist, gibt es eine entscheidende Tatsache, die Sie verstehen müssen: malloc() kann fehlschlagen. Wenn dem System der verfügbare Speicher ausgeht, kann malloc() Ihre Anfrage nicht erfüllen und gibt stattdessen NULL anstelle einer gültigen Speicheradresse zurück.
Das bedeutet, dass Sie jedes Mal, wenn Sie malloc() verwenden, überprüfen müssen, ob der Aufruf erfolgreich war, bevor Sie versuchen, den zurückgegebenen Pointer zu verwenden. Die Verwendung eines NULL-Pointers wird dazu führen, dass Ihr Programm mit einem Speicherzugriffsfehler (Segmentation Fault) abstürzt.
int *ptr = (int*)malloc(sizeof(int));
if (ptr == NULL) {
printf("Memory allocation failed!\n");
return -1; // Programm beenden oder den Fehler behandeln
}
// Hier kann ptr sicher verwendet werden
*ptr = 42;Diese NULL-Prüfung ist nicht optional – sie ist essenziell für das Schreiben robuster C-Programme. Auch wenn Fehler bei der Speicherreservierung auf modernen Systemen selten sind, können sie vorkommen, insbesondere in Umgebungen mit begrenzten Ressourcen oder wenn große Mengen an Speicher angefordert werden. Professioneller C-Code enthält immer diese Prüfungen, um Abstürze zu verhindern und eine kontrollierte Fehlerbehandlung zu ermöglichen.
Aufgabe
EinfachSchreiben Sie ein C-Programm, das eine ordnungsgemäße Fehlerbehandlung bei der Verwendung von malloc() für die dynamische Speicherallokation demonstriert. Ihr Programm sollte:
- Einen Integer
nvom Benutzer einlesen, der die Anzahl der zu speichernden Ganzzahlen darstellt - Verwenden Sie
malloc()mitsizeof(), um dynamisch Speicher für ein Array vonnIntegern zu allokieren - Prüfen Sie, ob die Speicherallokation erfolgreich war, indem Sie testen, ob der zurückgegebene Pointer
NULList - Wenn die Allokation fehlschlägt, geben Sie
Memory allocation failed!aus und beenden Sie das Programm - Wenn die Allokation erfolgreich ist, geben Sie
Memory allocation successful!aus - Lesen Sie
nInteger-Werte vom Benutzer ein und speichern Sie diese im allokierten Array - Berechnen und geben Sie die Summe aller Werte im Format
Sum: [value]aus - Geben Sie die Gesamtzahl der allokierten Bytes im Format
Bytes allocated: [value]aus
Denken Sie daran, den Header <stdlib.h> einzubinden, um malloc() zu verwenden. Ihr Programm muss die wesentliche Praxis der Überprüfung auf Allokationsfehler demonstrieren, bevor versucht wird, den allokierten Speicher zu verwenden.
Wenn die Eingabe zum Beispiel wie folgt aussieht:
4
10 20 30 40Sollte Ihre Ausgabe wie folgt aussehen:
Memory allocation successful!
Sum: 100
Bytes allocated: 16Diese Herausforderung unterstreicht die entscheidende Bedeutung der defensiven Programmierung bei der Arbeit mit dynamischer Speicherallokation und stellt sicher, dass Ihre Programme potenzielle Speicherallokationsfehler ordnungsgemäß behandeln, anstatt unerwartet abzustürzen.
Spickzettel
Überprüfen Sie immer, ob malloc() den Wert NULL zurückgibt, bevor Sie den zugewiesenen Speicher verwenden:
int *ptr = (int*)malloc(sizeof(int));
if (ptr == NULL) {
printf("Memory allocation failed!\n");
return -1; // Beenden Sie das Programm oder behandeln Sie den Fehler
}
// Hier kann ptr sicher verwendet werden
*ptr = 42;malloc() kann fehlschlagen, wenn dem System der verfügbare Speicher ausgeht. Die Verwendung eines NULL-Zeigers führt zu einem Segmentierungsfehler (Segmentation Fault). Diese NULL-Prüfung ist für das Schreiben robuster C-Programme und das Verhindern von Abstürzen unerlässlich.
Probier es selbst
#include <stdio.h>
#include <stdlib.h>
int main() {
// Lies die Anzahl der Ganzzahlen ein
int n;
scanf("%d", &n);
// TODO: Schreibe deinen Code hier
// - Verwende malloc(), um Speicher für n Ganzzahlen zu reservieren
// - Überprüfe, ob die Speicherreservierung erfolgreich war
// - Behandle sowohl Erfolgs- als auch Fehlerfälle
// - Lies die Ganzzahlen ein und speichere sie
// - Berechne die Summe und die reservierten Bytes
return 0;
}Diese Lektion enthält ein kurzes Quiz. Starte die Lektion, um es zu beantworten und deinen Fortschritt zu speichern.
Alle Lektionen in Logic & Flow
1Zeiger-Grundlagen
Was ist ein Zeiger?Zeiger deklarierenDer Adressoperator (&)Der Dereferenzierungsoperator (*)NULL-ZeigerZusammenfassung: Zeiger-Grundlagen4Projekt: Einfaches Text-Tool
ProjektübersichtZeichen zählen2Pointer und Arrays
Array-Namen als PointerArray-Elemente - PointerPointer-ArithmetikPointer vergleichenWiederholung: Array-Durchlauf mit Pointern5Zeiger und Funktionen
Wertübergabe (Pass-by-Value)Zeiger an Funktionen übergebenVariablen über Zeiger ändernEin klassisches Beispiel: SwapArrays an Funktionen übergebenZusammenfassung: Zeiger als Funktionsargumente8Structs und Zeiger
Zeiger auf StructsDer Pfeiloperator (->)Structs per Wert übergebenÜbergabe von Struct-ZeigernDynamische Allokation von StructsZusammenfassung: Struct ändern - Ptr11Finale Wiederholungsaufgaben
Wiederholung: Dynamische String-KonkatenationWiederholung: Array von StructsWiederholung: Wortfrequenz-Zähler3Character-Arrays und Strings
Strings als char-ArraysDer Null-TerminatorString-Eingabe mit scanfVerwendung von strlen()Verwendung von strcpy()Verwendung von strcat()Verwendung von strcmp()Zusammenfassung: Grundlegende String-Funktionen6Speicherverwaltung
Stack vs. Heap SpeicherDynamische Allokation - malloc()Verwendung von sizeof() für die AllokationÜberprüfung auf AllokationsfehlerSpeicher freigeben mit free()Allokation mit calloc()Rückblick: Dynamische Arrays