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, "...").
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:
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.
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.
perroraggiunge '\n'alla fine quindi il formato sarebbe "%s\n", no?
strerror_srealtà non è poi così male come interfaccia.
_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.
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));
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.
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"
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
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.