Biblioteka C nie jest ustawiona errnona 0 z powodów historycznych 1 . POSIX nie twierdzi już, że jego biblioteki nie zmienią wartości w przypadku sukcesu, a nowa strona podręcznika systemowego Linuxaerrno.h odzwierciedla to:
Plik <errno.h>nagłówkowy definiuje zmienną całkowitą errnoustawianą przez wywołania systemowe i niektóre funkcje biblioteczne w przypadku błędu wskazującego, co poszło nie tak. Jego wartość jest istotna tylko wtedy, gdy zwracana wartość wywołania wskazuje błąd (tj. -1Z większości wywołań systemowych -1lub NULLz większości funkcji bibliotecznych); funkcja, która udaje się możliwość zmian errno.
Uzasadnienie ANSI C stwierdza, że komitet uznał za bardziej praktyczne przyjęcie i ujednolicenie istniejącej praktyki używania errno.
Maszynę do zgłaszania błędów, skoncentrowaną na ustawieniu, na errnoogół uważa się w najlepszym przypadku z tolerancją. Wymaga to `` patologicznego sprzężenia '' między funkcjami biblioteki i wykorzystuje statyczną komórkę zapisywalną, co zakłóca budowę bibliotek z możliwością udostępniania. Niemniej jednak Komitet wolał ujednolicić istniejącą, choć niewystarczającą maszynę, niż wynaleźć coś bardziej ambitnego.
Prawie zawsze istnieje sposób na sprawdzenie błędu poza sprawdzeniem, czy errnozostał ustawiony. Sprawdzanie, czy errnoustawiony zestaw nie zawsze jest wiarygodne, ponieważ niektóre połączenia wymagają wywołania oddzielnego interfejsu API, aby uzyskać przyczynę błędu. Na przykład ferror()służy do sprawdzania błędu, jeśli otrzymasz krótki wynik z fread()lub fwrite().
Co ciekawe, przykładem użycia strtod()jest jeden z przypadków, w których ustawienie wartości errno0 przed wywołaniem jest wymagane do prawidłowego wykrycia błędu. Wszystkie funkcje strto*()ciąg do liczby mają ten wymóg, ponieważ poprawna wartość zwracana jest zwracana nawet w przypadku wystąpienia błędu.
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? */
}
}
Powyższy kod opiera się na zachowaniu strtod()zgodnie z dokumentacją w systemie Linux . Norma C stanowi jedynie, że niedomiar nie może zwrócić wartości większej niż najmniejszy dodatni double, a to, czy errnojest ustawiona, ERANGEjest zdefiniowane jako implementacja 2 .
W rzeczywistości istnieje obszerny zapis doradczy certyfikatu, który zaleca zawsze ustawienie errnona 0 przed wywołaniem biblioteki i sprawdzanie jego wartości po wywołaniu wskazującym na awarię . Wynika to z faktu, że niektóre wywołania biblioteki zostaną ustawione, errnonawet jeśli samo wywołanie zakończyło się pomyślnie 3 .
Wartość errno0 podczas uruchamiania programu, ale nigdy nie jest ustawiona na 0 przez żadną funkcję biblioteczną. Wartość errnomoże być ustawiona na niezerową przez wywołanie funkcji biblioteki, niezależnie od tego, czy wystąpił błąd, pod warunkiem, że użycie errnonie jest udokumentowane w opisie funkcji w standardzie C. Program ma sprawdzanie zawartości errnodopiero po zgłoszeniu błędu. Mówiąc dokładniej, errnoma znaczenie tylko wtedy, gdy funkcja biblioteki, która ustawia się errnona błąd, zwróciła kod błędu.
1. Wcześniej twierdziłem, że ma to na celu uniknięcie maskowania błędu z wcześniejszego połączenia. Nie mogę znaleźć żadnych dowodów na poparcie tego roszczenia. Miałem też fałszywy printf()przykład.
2. Dzięki @chux za zwrócenie na to uwagi. Odniesieniem jest C.11 § 7.22.1.3 ¶10.
3. Wskazane przez @KeithThompson w komentarzu.
errno, zawsze możesz sam ustawić zero.