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, "...")
.
La llamada perror
le 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 perror
inmediatamente 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 errno
se escribirá y la llamada perror
no 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
.
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.strerror
no es necesario que sea seguro para subprocesos. Es estúpido, pero ese es el estándar.strerror_l
se puede utilizar en su lugar como un reemplazo directo en los sistemas POSIX 2008.strerror_r
también está disponible en sistemas más antiguos, pero tiene problemas realmente desagradables con algunos sistemas que tienen versiones no compatibles.perror
agrega'\n'
al final para que el formato sea"%s\n"
, ¿no?strerror_s
realidad no es tan malo como interfaz._s
basura 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_s
debe usar toda la familia de funciones en lugar de las estándar.Hacen cosas bastante diferentes.
Usas
perror()
para imprimir un mensaje alstderr
que correspondeerrno
. Usasfprintf()
para imprimir cualquier cosa enstderr
, o cualquier otro flujo.perror()
es una función de impresión muy especializada:es equivalente a
fuente
perror(const char *s)
: imprime la cadena que le da seguida de una cadena que describe el valor actual deerrno
.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.fuente
perror () siempre escribe en stderr; strerr (), utilizado junto con fprintf (), puede escribir en cualquier salida, incluido stderr, pero no exclusivamente.
Además, el perror impone su propio formato de texto "texto: descripción del error"
fuente
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
fuente