ProgrammazioneSviluppatore C

Come viene gestito il trattamento degli errori nel linguaggio C? Quali sono le differenze tra setjmp/longjmp, errno e il ritorno del codice di errore? Quando utilizzare un approccio rispetto all'altro?

Supera i colloqui con l'assistente IA Hintsage

Risposta

Nel linguaggio C non esiste un supporto integrato per le eccezioni, il trattamento degli errori è implementato nei seguenti modi:

  1. Ritorno del codice di errore (di solito attraverso il valore di ritorno della funzione) Esempio:

    int read_file(const char *name) { FILE *f = fopen(name, "r"); if (!f) return -1; // Errore // ... fclose(f); return 0; // Successo }
  2. Utilizzo della variabile globale errno In caso di errore, le funzioni standard impostano spesso la variabile globale errno. Esempio:

    FILE *fp = fopen("nofile", "r"); if (!fp) { perror("Errore file"); // errno definisce la causa }
  3. setjmp/longjmp — meccanismo di lancio di "eccezioni" (il contesto di esecuzione viene salvato e ripristinato) Utilizzato per casi complessi (ad esempio, terminazione di emergenza interlivello). Usato raramente, poiché complica il codice e può portare a perdite di risorse.

    #include <setjmp.h> jmp_buf buf; if (setjmp(buf) == 0) { // ... longjmp(buf, 1); // Passa a if (setjmp(...)) } else { // Trattamento dell'errore }
  • Ritorno del codice di errore — metodo principale, semplice e sicuro.
  • errno — conveniente per le funzioni di libreria.
  • setjmp/longjmp — per casi specifici (librerie complesse o interpreti).

Domanda insidiosa

Cosa stamperà il seguente codice?

#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; }

Risposta:

  • Alla prima chiamata setjmp restituisce 0 e viene chiamata la funzione func.
  • In essa si verifica longjmp(buf, 5), l'esecuzione torna a setjmp, che ora restituisce 5.
  • L'output finale:
    val=0
    val=5
    

Esempi di errori reali dovuti alla mancanza di conoscenza delle sfumature dell'argomento


Storia In una libreria è stato implementato un meccanismo manuale di pulizia delle risorse in caso di errore solo per codice di ritorno. Ma il programmatore ha dimenticato di gestire l'errore nel ritorno non dal thread principale, ma da callback (tramite setjmp/longjmp), risultando in perdite di memoria e blocchi di file.


Storia In un'applicazione di rete è stata trascurata la verifica di errno dopo l'operazione socket. A causa di ciò si è verificata una diagnosi errata: la variabile errno ha mantenuto un valore precedente errato dalla funzione precedente.


Storia Il team ha implementato una complessa nidificazione con numerosi punti di ritorno del codice di errore, ma non ha seguito la convenzione sui valori di ritorno (zero/valori negativi). Alcuni errori sono stati interpretati come successi, portando a guasti imprevedibili del servizio.