Biblioteka C nie jest ustawiona errno
na 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ą errno
ustawianą 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. -1
Z większości wywołań systemowych -1
lub NULL
z 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 errno
ogół 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 errno
został ustawiony. Sprawdzanie, czy errno
ustawiony 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 errno
0 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 errno
jest ustawiona, ERANGE
jest zdefiniowane jako implementacja 2 .
W rzeczywistości istnieje obszerny zapis doradczy certyfikatu, który zaleca zawsze ustawienie errno
na 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, errno
nawet jeśli samo wywołanie zakończyło się pomyślnie 3 .
Wartość errno
0 podczas uruchamiania programu, ale nigdy nie jest ustawiona na 0 przez żadną funkcję biblioteczną. Wartość errno
może być ustawiona na niezerową przez wywołanie funkcji biblioteki, niezależnie od tego, czy wystąpił błąd, pod warunkiem, że użycie errno
nie jest udokumentowane w opisie funkcji w standardzie C. Program ma sprawdzanie zawartości errno
dopiero po zgłoszeniu błędu. Mówiąc dokładniej, errno
ma znaczenie tylko wtedy, gdy funkcja biblioteki, która ustawia się errno
na 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.