La biblioteca C no se establece errno
en 0 por razones históricas 1 . POSIX ya no afirma que sus bibliotecas no alterarán el valor en caso de éxito, y la nueva página de manual de Linuxerrno.h
refleja esto:
El <errno.h>
archivo de encabezado define la variable entera errno
, que se establece mediante llamadas al sistema y algunas funciones de la biblioteca en caso de error para indicar qué salió mal. Su valor es significativo solo cuando el valor de retorno de la llamada indica un error (es decir, -1
de la mayoría de las llamadas al sistema; -1
o NULL
de la mayoría de las funciones de la biblioteca); una función que tiene éxito se permitió al cambio errno
.
La justificación ANSI C establece que el comité consideró que era más práctico adoptar y estandarizar la práctica existente de uso errno
.
La maquinaria de informe de errores centrada en la configuración de errno
generalmente se considera con tolerancia en el mejor de los casos. Requiere un `` acoplamiento patológico '' entre las funciones de la biblioteca y hace uso de una celda de memoria de escritura estática, que interfiere con la construcción de bibliotecas compartibles. Sin embargo, el Comité prefirió estandarizar esta maquinaria existente, aunque deficiente, en lugar de inventar algo más ambicioso.
Casi siempre hay una manera de verificar si hay errores fuera de verificar si errno
se configuró. Comprobar si errno
se configuró no siempre es confiable, ya que algunas llamadas requieren llamar a una API separada para obtener el motivo del error. Por ejemplo, ferror()
se usa para buscar un error si obtiene un resultado corto de fread()
o fwrite()
.
Curiosamente, su ejemplo de uso strtod()
es uno de los casos en errno
los que se requiere establecer 0 antes de la llamada para detectar correctamente si se ha producido un error. Todas las strto*()
funciones de cadena a número tienen este requisito, porque se devuelve un valor de retorno válido incluso ante un error.
errno = 0;
char *endptr;
double x = strtod(str1, &endptr);
if (endptr == str1) {
/*...parse error */
} else if (errno == ERANGE) {
if (x == 0) {
/*...underflow */
} else if (x == HUGE_VAL) {
/*...positive overflow */
} else if (x == -HUGE_VAL) {
/*...negative overflow */
} else {
/*...unknown range error? */
}
}
El código anterior se basa en el comportamiento de strtod()
lo documentado en Linux . El estándar C solo estipula que el subflujo no puede devolver un valor mayor que el positivo más pequeño double
, y si la errno
configuración ERANGE
está definida o no, la implementación está definida 2 .
En realidad, hay una extensa redacción de aviso de certificación que recomienda establecer siempre errno
a 0 antes de una llamada a la biblioteca y verificar su valor después de que la llamada indica que se ha producido una falla . Esto se debe a que algunas llamadas de la biblioteca se establecerán errno
incluso si la llamada en sí fue exitosa 3 .
El valor de errno
es 0 al inicio del programa, pero ninguna función de biblioteca establece nunca a 0. Una errno
llamada a la función de biblioteca puede establecer un valor distinto de cero si existe o no un error, siempre que el uso de errno
no esté documentado en la descripción de la función en el Estándar C. Es significativo que un programa inspeccione el contenido errno
solo después de que se haya informado un error. Más precisamente, errno
es significativo solo después de que una función de biblioteca que se establece errno
en error ha devuelto un código de error.
1. Anteriormente dije que era para evitar enmascarar un error de una llamada anterior. No puedo encontrar ninguna evidencia para apoyar esta afirmación. También tuve un printf()
ejemplo falso .
2. Gracias a @chux por señalar esto. La referencia es C.11 §7.22.1.3 ¶10.
3. Señalado por @KeithThompson en un comentario.
errno
, siempre puedes ponerlo a cero tú mismo.