¿Cuándo debería usar perror (“…”) y fprintf (stderr, “…”)?

105

Leer las páginas de manual y algo de código no me ayudó realmente a comprender la diferencia entre, o mejor, cuándo debería usar perror("...")o fprintf(stderr, "...").

freeboy1015
fuente

Respuestas:

113

La llamada perrorle dará el valor interpretado de errno, que es un valor de error local de subproceso escrito por las llamadas al sistema POSIX (es decir, cada subproceso tiene su propio valor para errno). Por ejemplo, si hizo una llamada a open()y se generó un error (es decir, regresó -1), puede llamar perrorinmediatamente después para ver cuál fue el error real. Tenga en cuenta que si llama a otras llamadas al sistema mientras tanto, el valor en errnose escribirá y la llamada perrorno será de ninguna utilidad para diagnosticar su problema si un error fue generado por una llamada al sistema anterior.

fprintf(stderr, ...)por otro lado, se puede utilizar para imprimir sus propios mensajes de error personalizados. Al imprimir en stderr, evita que la salida del informe de errores se mezcle con la salida "normal" que debería ir a stdout.

Tenga en cuenta que fprintf(stderr, "%s\n", strerror(errno))es similar a perror(NULL)ya que una llamada a strerror(errno)generará el valor de la cadena impresa para errno, y luego puede combinarlo con cualquier otro mensaje de error personalizado a través de fprintf.

Jason
fuente
3
oh, lo tengo. La función de perror funciona de manera diferente dependiendo del valor de errno. If you use a function that effects errno then it makes sense to use perror.Si usa una función que no afecta a errno y simplemente devuelve un código de error, debe usar fprintf (stderr, fmt, ...). Por ejemplo, strtol devolverá LONG_MAX o LONG_MIN si una cadena está fuera de rango y establecerá errno en ERANGE. Entonces, si strtol falla debido a que está fuera de rango, usaría perror.
freeboy1015
6
Un detalle, strerrorno es necesario que sea seguro para subprocesos. Es estúpido, pero ese es el estándar. strerror_lse puede utilizar en su lugar como un reemplazo directo en los sistemas POSIX 2008. strerror_rtambién está disponible en sistemas más antiguos, pero tiene problemas realmente desagradables con algunos sistemas que tienen versiones no compatibles.
R .. GitHub DEJA DE AYUDAR A ICE
también como un detalle, creo que perroragrega '\n'al final para que el formato sea "%s\n", ¿no?
Jens Gustedt
1
@R .., ja, ya lo he hecho, y que yo sepa no me están pagando nada. Y dado que MS parece estar cortando su soporte para C por completo, al final seré el único :) en strerror_srealidad no es tan malo como interfaz.
Jens Gustedt
2
¿Soporte de corte por completo? Parece que volvieron a engañar al comité. Introducir su _sbasura en el estándar fue básicamente un juego de MS ("Si adopta nuestras interfaces, consideraremos que nuestros productos sean compatibles con su estándar") y, por supuesto, ahora no lo están cumpliendo. De hecho, estoy de acuerdo en que esta interfaz no es mala en sí misma. Lo malo es la propaganda (en forma de advertencias del compilador) de que la mayoría de la biblioteca estándar es "insegura" y que se _sdebe usar toda la familia de funciones en lugar de las estándar.
R .. GitHub DEJA DE AYUDAR A ICE
40

Hacen cosas bastante diferentes.

Usas perror()para imprimir un mensaje al stderrque corresponde errno. Usas fprintf()para imprimir cualquier cosa en stderr, o cualquier otro flujo. perror()es una función de impresión muy especializada:

perror(str);

es equivalente a

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

perror(const char *s): imprime la cadena que le da seguida de una cadena que describe el valor actual de errno.

stderr: es un flujo de salida que se usa para canalizar sus propios mensajes de error a (predeterminado en el terminal).

Pertinente:

char *strerror(int errnum): dale un número de error y devolverá la cadena de error asociada.

Adib Saad
fuente
2

perror () siempre escribe en stderr; strerr (), utilizado junto con fprintf (), puede escribir en cualquier salida, incluido stderr, pero no exclusivamente.

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

Además, el perror impone su propio formato de texto "texto: descripción del error"

Sébastien
fuente
-2

La función de error toma más tiempo para realizar la ejecución, la llamada va del espacio del usuario al espacio del kernal, mientras que las llamadas de fprintf van de api a kernal

vivek singh
fuente