Le funzioni perror e strerror in Linguaggio C

Concetti Chiave
  • La funzione perror stampa un messaggio di errore sullo standard error (stderr) basato sul valore corrente di errno, fornendo una descrizione testuale dell'errore.
  • La funzione strerror restituisce una stringa descrittiva dell'errore associato a un valore specifico di errno, permettendo di ottenere la descrizione senza stamparla immediatamente.
  • Entrambe le funzioni sono utili per migliorare la gestione degli errori nei programmi scritti in linguaggio C, rendendo i messaggi di errore più comprensibili per gli utenti.
  • perror è particolarmente utile per stampare messaggi di errore direttamente quando si verifica un errore, mentre strerror è utile quando si desidera manipolare o memorizzare la descrizione dell'errore.

La funzione perror

Nella lezione precedente abbiamo visto come alcune funzioni della libreria standard del C utilizzano la variabile globale errno per segnalare errori. In caso di funzionamento anomalo, queste funzioni impostano errno a un valore specifico che indica il tipo di errore verificatosi.

Quando ciò accade, è spesso utile fornire all'utente un messaggio di errore più descrittivo, che spieghi la natura dell'errore in modo comprensibile. Per questo scopo, il linguaggio C mette a disposizione la funzione perror che sta, appunto, per "print error" (stampa errore).

Questa funzione è definita nell'header <stdio.h> e ha la seguente firma:

void perror(const char *s);

Quando viene invocata, la funzione perror effettua 5 operazioni:

  1. Controlla il valore corrente di errno.
  2. Recupera la descrizione testuale associata a quel valore di errno.
  3. Stampa la stringa passata come argomento s, seguita da due punti e uno spazio (": ").
  4. Stampa la descrizione testuale dell'errore.
  5. Termina la stampa con un carattere di nuova linea.

Per capire come funziona, riprendiamo l'esempio del calcolo della radice quadrata di un numero reale attraverso la funzione sqrt della libreria matematica <math.h>. Questa funzione imposta errno a EDOM (domain error) se viene chiamata con un argomento negativo.

Possiamo utilizzare perror per stampare un messaggio di errore più chiaro quando si verifica questo problema:

#include <stdio.h>
#include <math.h>
#include <errno.h>

int main() {
    double numero;
    printf("Inserisci un numero reale: ");
    scanf("%lf", &numero);

    errno = 0; // Resetta errno prima della chiamata
    double risultato = sqrt(numero);

    if (errno != 0) {
        perror("Errore nel calcolo della radice quadrata");
    } else {
        printf("La radice quadrata di %.2f è %.2f\n", numero, risultato);
    }

    return 0;
}

Provando a compilare ed eseguire il codice di sopra, se inseriamo un numero negativo, otterremo un output simile al seguente:

Inserisci un numero reale: -9
Errore nel calcolo della radice quadrata: Numerical argument out of domain

Inoltre, la funzione perror stampa il messaggio di errore direttamente sullo standard error (stderr), il che è utile per separare i messaggi di errore dall'output normale del programma.

Il messaggio di errore stampato da perror dipende dal valore di errno e dalla configurazione locale del sistema, quindi potrebbe variare leggermente tra diverse piattaforme o ambienti.

Nel caso di un errore EDOM, il messaggio predefinito è "Numerical argument out of domain", ma altri errori avranno messaggi diversi.

La funzione strerror

A volte, potrebbe essere necessario ottenere la descrizione testuale di un errore senza stamparla immediatamente. In questi casi, possiamo utilizzare la funzione strerror, definita nell'header <string.h>, che restituisce una stringa descrittiva dell'errore associato a un valore specifico di errno.

La firma della funzione strerror è la seguente:

char *strerror(int errnum);

Alla funzione strerror deve essere passato un intero errnum, che rappresenta il valore di errno per il quale si desidera ottenere la descrizione testuale. La funzione restituisce un puntatore a una stringa che contiene la descrizione dell'errore.

Questa funzione è strettamente correlata a perror, in quanto perror adopera internamente strerror per ottenere la descrizione dell'errore da stampare.

Inoltre, non è necessario che errnum sia necessariamente il valore corrente di errno; possiamo passare qualsiasi valore di errore valido per ottenere la sua descrizione.

Ad esempio, possiamo realizzare un programma che utilizza strerror per ottenere e stampare la descrizione di un errore specifico:

#include <stdio.h>
#include <string.h>
#include <errno.h>

int main() {
    int errore;

    printf("Inserisci un numero di errore (ad esempio, %d per EDOM): ", EDOM);
    scanf("%d", &errore);
    char *descrizione = strerror(errore);
    printf("Descrizione dell'errore %d: %s\n", errore, descrizione);

    return 0;
}

Compilando ed eseguendo il programma sopra, se inseriamo 33 (che corrisponde a EDOM su molti sistemi, ad esempio su Linux), otterremo un output simile al seguente:

Inserisci un numero di errore (ad esempio, 33 per EDOM): 33
Descrizione dell'errore 33: Numerical argument out of domain

In questo modo, strerror ci consente di ottenere la descrizione testuale di un errore specifico senza dover necessariamente stampare immediatamente il messaggio di errore.