A biblioteca C não define errno
como 0 por razões históricas 1 . O POSIX não afirma mais que suas bibliotecas não alterarão o valor em caso de sucesso, e a nova página de manual do Linuxerrno.h
reflete isso:
O <errno.h>
arquivo de cabeçalho define a variável inteira errno
, que é definida por chamadas do sistema e algumas funções da biblioteca no caso de um erro para indicar o que deu errado. Seu valor é significativo apenas quando o valor de retorno da chamada indica um erro (ou seja, -1
da maioria das chamadas do sistema; -1
ou NULL
da maioria das funções da biblioteca); uma função que sucede é permitida a mudança errno
.
A justificativa do ANSI C afirma que o comitê considerou mais prático adotar e padronizar a prática existente de uso errno
.
O mecanismo de relatório de erros centrado na configuração de errno
é geralmente considerado com tolerância, na melhor das hipóteses. Requer um `` acoplamento patológico '' entre as funções da biblioteca e faz uso de uma célula de memória gravável estática, que interfere na construção de bibliotecas compartilháveis. No entanto, o Comitê preferiu padronizar esse mecanismo existente, embora deficiente, em vez de inventar algo mais ambicioso.
Quase sempre existe uma maneira de verificar se há erros fora da verificação, se errno
tiver sido definido. Verificar se errno
o conjunto foi configurado nem sempre é confiável, pois algumas chamadas exigem a chamada de uma API separada para obter o motivo do erro. Por exemplo, ferror()
é usado para verificar se há um pequeno resultado de fread()
ou fwrite()
.
Curiosamente, seu exemplo de uso strtod()
é um dos casos em que errno
é necessário definir 0 antes da chamada para detectar corretamente se ocorreu um erro. Todas as strto*()
funções string para number têm esse requisito, porque um valor de retorno válido é retornado mesmo diante de um erro.
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? */
}
}
O código acima é baseado no comportamento de strtod()
conforme documentado no Linux . O padrão C apenas estipula que o subfluxo não pode retornar um valor maior que o menor positivo double
e se está ou não errno
definido como está definido para ERANGE
implementação 2 .
Na verdade, existe uma extensa redação de recomendação de certificado que recomenda sempre definir errno
0 antes de uma chamada de biblioteca e verificar seu valor após a chamada indicar que ocorreu uma falha . Isso ocorre porque algumas chamadas de biblioteca serão definidas errno
mesmo que a chamada em si tenha sido bem-sucedida 3 .
O valor de errno
é 0 na inicialização do programa, mas nunca é definido como 0 por nenhuma função da biblioteca. O valor de errno
pode ser definido como diferente de zero por uma chamada de função de biblioteca, havendo ou não um erro, desde que o uso de errno
não esteja documentado na descrição da função no Padrão C. É significativo para um programa inspecionar o conteúdo errno
somente após um erro ter sido relatado. Mais precisamente, errno
só é significativo depois que uma função de biblioteca que define errno
erro retorna um código de erro.
1. Anteriormente, afirmei que era para evitar mascarar um erro de uma chamada anterior. Não consigo encontrar nenhuma evidência para apoiar esta afirmação. Eu também tive um printf()
exemplo falso .
2. Obrigado ao @chux por apontar isso. A referência é C.11 §7.22.1.3 ¶10.
3. Apontado por @KeithThompson em um comentário.
errno
, pode sempre defini-lo como zero.