ProgrammierungC-Entwickler

Wie wird die Fehlerbehandlung in der Programmiersprache C umgesetzt? Was sind die Unterschiede zwischen setjmp/longjmp, errno und der Rückgabe eines Fehlercodes? Wann sollte man welchen Ansatz verwenden?

Bestehen Sie Vorstellungsgespräche mit dem Hintsage-KI-Assistenten

Antwort

In der Programmiersprache C gibt es keine eingebaute Unterstützung für Ausnahmen, die Fehlerbehandlung wird auf folgende Weise umgesetzt:

  1. 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 }
  2. 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 }
  3. 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 }
  • Rückgabe eines Fehlercodes — der Hauptansatz, einfach und sicher.
  • errno — praktisch für Bibliotheksfunktionen.
  • setjmp/longjmp — für spezielle Fälle (komplexe Bibliotheken oder Interpreter).

Trickfrage

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:

  • Beim ersten Aufruf von setjmp gibt 0 zurück und die Funktion func wird aufgerufen.
  • In dieser wird longjmp(buf, 5) ausgeführt, die Ausführung springt zurück zu setjmp, das jetzt 5 zurückgibt.
  • Die endgültige Ausgabe:
    val=0
    val=5
    

Beispiele für reale Fehler aufgrund mangelnden Wissens über die Feinheiten des Themas


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 errno nach einer Socket-Operation übersehen. Dadurch entstand eine falsche Diagnose: die Variable errno behielt 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.