El estándar C exige que ninguna función de biblioteca estándar C se establezca errno
en cero. ¿Por qué es esto exactamente?
Podría entender que es útil para llamar a varias funciones y solo verificar errno
después de la última, por ejemplo:
errno = 0;
double x = strtod(str1, NULL);
long y = strtol(str2, NULL);
if (errno)
// either "strtod" or "strtol" failed
else
// both succeeded
Sin embargo, ¿esto no se considera "mala práctica"? Dado que sólo está comprobando errno
al final, sólo se sabe que una de las funciones hicieron fallar, pero no la que función ha fallado. ¿Simplemente saber que algo falló es lo suficientemente bueno para la mayoría de los programas prácticos?
Intenté buscar varios documentos de Fundamentos de C, pero muchos de ellos no tienen muchos detalles <errno.h>
.
errno
, siempre puedes ponerlo a cero tú mismo.errno
en un valor distinto de cero, incluso si tiene éxito. (Podría llamar a alguna otra función que falla, pero eso no constituye una falla en la función externa.)Respuestas:
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: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
.Casi siempre hay una manera de verificar si hay errores fuera de verificar si
errno
se configuró. Comprobar sierrno
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 defread()
ofwrite()
.Curiosamente, su ejemplo de uso
strtod()
es uno de los casos enerrno
los que se requiere establecer 0 antes de la llamada para detectar correctamente si se ha producido un error. Todas lasstrto*()
funciones de cadena a número tienen este requisito, porque se devuelve un valor de retorno válido incluso ante un 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ñodouble
, y si laerrno
configuraciónERANGE
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ánerrno
incluso si la llamada en sí fue exitosa 3 .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.
fuente
errno
en laERANGE
implementación se define en el caso de subflujo, en realidad no hay una forma portátil de detectar el subflujo. Mi código siguió lo que encontré en la página de manual de Linux en mi sistema.strto*
funciones son exactamente la razón por la que pregunté si mi ejemplo se consideraría una mala práctica, pero es la única forma en queerrno
no se establecería en cero sería útil, o incluso aplicable.errno
puede establecerse incluso en caso de éxito, por lo que el solo hecho de que se haya configurado no es realmente un indicador suficientemente bueno de que se haya producido un error. Debe verificar los resultados de las llamadas individuales para saber si ocurrió un error.Puede hacer una verificación de errores para ambas llamadas de función, si realmente le importa.
Como nunca sabemos cómo se llamó a la función mach en un proceso, ¿cómo puede la biblioteca establecer errores para cada llamada a la función?
fuente
Cambiar arbitrariamente el error no es análogo a 'atrapar y tragar' una excepción. Antes de que hubiera excepciones que se propagaran a través de diferentes capas de un programa y finalmente llegaran a un punto en el que la persona que llama capturaría y respondería a la excepción de alguna manera o simplemente pasaría el dinero, había errores. No alterar el error, a menos que de alguna manera esté manejando, anulando, tratando como irrelevante, el error, es esencial para este paradigma de propagación de manejo de errores de primera generación.
fuente