La gestione degli errori nel linguaggio C è sempre stata compito dello sviluppatore. Nella libreria standard non ci sono eccezioni, gli errori vengono restituiti tramite codici di ritorno o una variabile globale errno (inizio utilizzo – UNIX anni '70, poi POSIX e ANSI C). Tali meccanismi sono usati anche oggi per gestire il flusso di esecuzione in situazioni anomale.
Gli errori nel lavoro con le funzioni standard (operazioni su file, allocazione di memoria, funzioni di stringa) possono passare inosservati senza un controllo specifico. Un'elaborazione errata – ignorare il codice di ritorno, interpretare erroneamente errno, non liberare le risorse – porta a un funzionamento scorretto del programma, crash e vulnerabilità.
Una corretta gestione degli errori richiede un'analisi obbligatoria dei valori restituiti dalle funzioni, l'uso di errno solo subito dopo un fallimento e un'uscita informativa degli errori. I codici di ritorno sono preferibili per le funzioni interne – consentono una gestione senza effetti collaterali globali. errno è usato più frequentemente con le chiamate di sistema e le funzioni della libreria standard. Dopo ogni operazione potenzialmente pericolosa viene analizzato il ritorno, e lo stato globale (errno) non deve essere sovrascritto da chiamate intermedie.
Esempio di codice:
#include <stdio.h> #include <errno.h> #include <string.h> FILE *open_file(const char *filename) { errno = 0; FILE *f = fopen(filename, "r"); if (!f) { fprintf(stderr, "Errore: %s ", strerror(errno)); } return f; }
Caratteristiche chiave:
Si può utilizzare errno per funzioni utente, se si vuole passare gli errori verso l'alto?
No, errno è destinata solo a chiamate di libreria standard e di sistema. È globale, può essere sovrascritta in qualsiasi punto e non è adatta per le proprie funzioni.
È obbligatorio impostare errno prima di ogni chiamata di funzione?
No, ma si raccomanda di azzerare errno (ad esempio, a zero) prima delle chiamate, se si intende analizzare le modifiche. Non ogni funzione modifica errno al successo, ma solo in caso di errore.
errno = 0; ... chiamata funzione pericolosa ...
Si può fare affidamento su errno dopo qualsiasi funzione?
Solo per quelle funzioni che secondo lo standard la impostano esplicitamente in caso di fallimento. Molte funzioni della libreria standard non toccano errno in caso di successo. La documentazione è la tua amica.
Apertura di un file senza controllare il risultato, gli errori non vengono analizzati, il programma funziona in modo errato in assenza del file:
Vantaggi:
Svantaggi:
Dopo ogni funzione critica il risultato viene controllato, in caso di errore viene restituito un messaggio dettagliato con strerror(errno), l'esecuzione termina correttamente:
Vantaggi:
Svantaggi: