In der Programmiersprache C gibt es keine eingebaute Unterstützung für Ausnahmen, die Fehlerbehandlung wird auf folgende Weise umgesetzt:
Rückgabe eines Fehlercodes (in der Regel über den Rückgabewert der Funktion) Beispiel:
int read_file(const char *name) { FILE *f = fopen(name, "r"); if (!f) return -1; // Fehler // ... fclose(f); return 0; // Erfolg }
Verwendung der globalen Variablen errno
Bei einem Fehler setzen Standardfunktionen oft die globale Variable errno.
Beispiel:
FILE *fp = fopen("nofile", "r"); if (!fp) { perror("Dateifehler"); // errno bestimmt den Grund }
setjmp/longjmp — ein Mechanismus zum Werfen einer „Ausnahme“ (der Ausführungskontext wird gespeichert und wiederhergestellt) Wird für komplexe Fälle verwendet (z.B. notfallmäßiges Beenden über mehrere Ebenen). Wird selten verwendet, da es den Code kompliziert und zu Ressourcenlecks führen kann.
#include <setjmp.h> jmp_buf buf; if (setjmp(buf) == 0) { // ... longjmp(buf, 1); // springt zurück zu if (setjmp(...)) } else { // Fehlerbehandlung }
Was wird der folgende Code ausgeben?
#include <stdio.h> #include <setjmp.h> jmp_buf buf; void func() { longjmp(buf, 5); } int main() { int val = setjmp(buf); printf("val=%d\n", val); if (val == 0) func(); return 0; }
Antwort:
setjmp gibt 0 zurück und die Funktion func wird aufgerufen.longjmp(buf, 5) ausgeführt, die Ausführung springt zurück zu setjmp, das jetzt 5 zurückgibt.val=0
val=5
Geschichte In einer Bibliothek wurde ein manueller Mechanismus zur Bereinigung von Ressourcen bei einem Fehler nur nach dem Rückgabecode implementiert. Der Programmierer vergaß jedoch, den Fehler beim Rückgeben nicht aus dem Hauptthread, sondern aus einem Callback (über setjmp/longjmp) zu behandeln, was zu Speicherlecks und Dateisperren führte.
Geschichte In einer Netzwerk-Anwendung wurde die Überprüfung von
errnonach einer Socket-Operation übersehen. Dadurch entstand eine falsche Diagnose: die Variableerrnobehielt den alten inkorrekten Wert von der vorherigen Funktion.
Geschichte Das Team implementierte eine komplexe Verschachtelung mit vielen Rückgabepunkten für Fehlercodes, hielt sich jedoch nicht an die Konventionen bezüglich der Rückgabewerte (null/negative Werte). Einige Fehler wurden als erfolgreich interpretiert, was zu unvorhersehbaren Dienstfehlern führte.