Quando dovrei usare perror ("...") e fprintf (stderr, "...")?


105

Leggere le pagine man e un po 'di codice non mi ha davvero aiutato a capire la differenza tra - o meglio, quando avrei dovuto usare - perror("...")o fprintf(stderr, "...").

Risposte:


113

La chiamata perrorti darà il valore interpretato di errno, che è un valore di errore locale del thread scritto dalle chiamate di sistema POSIX (cioè, ogni thread ha il proprio valore per errno). Ad esempio, se hai effettuato una chiamata a open()e si è verificato un errore (ovvero è stato restituito -1), puoi chiamare perrorsubito dopo per vedere qual è stato l'errore effettivo. Tieni presente che se nel frattempo chiami altre chiamate di sistema, il valore in errnoverrà sovrascritto e la chiamata perrornon sarà di alcuna utilità per diagnosticare il problema se un errore è stato generato da una precedente chiamata di sistema.

fprintf(stderr, ...)d'altra parte può essere utilizzato per stampare i propri messaggi di errore personalizzati. Stampando su stderr, si evita che l'output di segnalazione degli errori venga mischiato con l'output "normale" che dovrebbe avere stdout.

Tieni presente che fprintf(stderr, "%s\n", strerror(errno))è simile a perror(NULL)poiché una chiamata a strerror(errno)genererà il valore di stringa stampato per errnoe puoi quindi combinarlo con qualsiasi altro messaggio di errore personalizzato tramite fprintf.


3
oh, capito. La funzione perror funziona in modo diverso a seconda del valore di errno. If you use a function that effects errno then it makes sense to use perrorSe usi una funzione che non ha effetto su errno e restituisce semplicemente un codice di errore dovresti usare fprintf (stderr, fmt, ...). Ad esempio, strtol restituirà LONG_MAX o LONG_MIN se una stringa è fuori intervallo e imposta errno su ERANGE. Quindi se strtol fallisce a causa di fuori intervallo, userei perror.
freeboy1015

6
Un dettaglio, strerrornon è necessario essere thread-safe. È stupido, ma questo è lo standard. strerror_lpuò essere utilizzato invece come sostituto immediato sui sistemi POSIX 2008. strerror_rè disponibile anche su sistemi meno recenti, ma presenta problemi davvero fastidiosi con alcuni sistemi che ne hanno versioni non conformi.
R .. GitHub SMETTA DI AIUTARE IL GHIACCIO

anche come pignolo, secondo me perroraggiunge '\n'alla fine quindi il formato sarebbe "%s\n", no?
Jens Gustedt

1
@R .., ah, l'ho già fatto, e per quanto ne so non mi stanno pagando nulla. E poiché MS sembra tagliare completamente il supporto per C, alla fine sarò l'unico :) in strerror_srealtà non è poi così male come interfaccia.
Jens Gustedt

2
Taglio completo del supporto? Sembra che abbiano ingannato di nuovo il comitato. Portare la loro _sspazzatura nello standard era fondamentalmente un gioco di MS ("Se adotti le nostre interfacce, prenderemo in considerazione l'idea di far sì che i nostri prodotti supportino il tuo standard") e ovviamente ora non stanno seguendo. In realtà sono d'accordo che questa interfaccia non è male in sé. Ciò che è negativo è la propaganda (sotto forma di avvertimenti del compilatore) secondo cui la maggior parte della libreria standard è "non sicura" e che l'intera famiglia di _sfunzioni dovrebbe essere utilizzata al posto di quelle standard.
R .. GitHub SMETTA DI AIUTARE IL GHIACCIO

40

Fanno cose piuttosto diverse.

Si utilizza perror()per stampare un messaggio a stderrcui corrisponde errno. Utilizzi fprintf()per stampare qualsiasi cosa su stderro qualsiasi altro flusso. perror()è una funzione di stampa molto specializzata:

perror(str);

è equivalente a

if (str)
    fprintf(stderr, "%s: %s\n", str, strerror(errno));
else
    fprintf(stderr, "%s\n", strerror(errno));

12

perror(const char *s): stampa la stringa che gli dai seguita da una stringa che descrive il valore corrente di errno.

stderr: è un flusso di output utilizzato per reindirizzare i propri messaggi di errore (predefinito al terminale).

Pertinente:

char *strerror(int errnum): dagli un numero di errore e restituirà la stringa di errore associata.


2

perror () scrive sempre su stderr; strerr (), usato insieme a fprintf (), può scrivere su qualsiasi output, incluso stderr ma non esclusivamente.

fprintf(stdout, "Error: %s", strerror(errno));
fprintf(stderr, "Error: %s", strerror(errno)); // which is equivalent to perror("Error")

Inoltre, perror impone la propria formattazione del testo "testo: descrizione errore"


-2

La funzione Perror impiega più tempo per eseguire la chiamata va dallo spazio utente allo spazio kernel dove fprintf chiama goest da api a kernal

Utilizzando il nostro sito, riconosci di aver letto e compreso le nostre Informativa sui cookie e Informativa sulla privacy.
Licensed under cc by-sa 3.0 with attribution required.