Die C-Bibliothek wird errno
aus historischen Gründen nicht auf 0 gesetzt 1 . POSIX behauptet nicht mehr, dass seine Bibliotheken den Wert im Erfolgsfall nicht ändern werden, und die neue Linux-Manpage fürerrno.h
spiegelt dies wider:
Die <errno.h>
Header-Datei definiert die Ganzzahlvariable errno
, die durch Systemaufrufe und einige Bibliotheksfunktionen im Fehlerfall festgelegt wird, um anzuzeigen, was schief gelaufen ist. Sein Wert ist nur dann von Bedeutung, wenn der Rückgabewert des Aufrufs einen Fehler anzeigt (dh -1
von den meisten Systemaufrufen -1
oder NULL
von den meisten Bibliotheksfunktionen). eine Funktion , die erfolgreich ist , zu ändern erlaubt errno
.
Die ANSI C-Begründung besagt, dass der Ausschuss es für praktischer hielt, die bestehende Verwendungspraxis zu übernehmen und zu standardisieren errno
.
Die Fehlermeldemaschinerie, die sich auf die Einstellung von konzentriert, errno
wird im Allgemeinen bestenfalls mit Toleranz betrachtet. Es erfordert eine "pathologische Kopplung" zwischen Bibliotheksfunktionen und verwendet eine statische beschreibbare Speicherzelle, die den Aufbau gemeinsam nutzbarer Bibliotheken stört. Der Ausschuss zog es jedoch vor, diese vorhandenen, jedoch mangelhaften Maschinen zu standardisieren, anstatt etwas Ehrgeizigeres zu erfinden.
Es gibt fast immer eine Möglichkeit, außerhalb der Überprüfung auf Fehler auf Fehler zu prüfen errno
. Das Überprüfen, ob errno
gesetzt wurde, ist nicht immer zuverlässig, da für einige Aufrufe eine separate API aufgerufen werden muss, um den Fehlergrund zu ermitteln. ferror()
Wird beispielsweise verwendet, um nach einem Fehler zu suchen, wenn Sie ein kurzes Ergebnis von fread()
oder erhalten fwrite()
.
Interessanterweise ist Ihr Beispiel für die Verwendung strtod()
einer der Fälle, in denen die Einstellung errno
auf 0 vor dem Aufruf erforderlich ist , um korrekt zu erkennen, ob ein Fehler aufgetreten ist. Für alle strto*()
String-to-Number-Funktionen gilt diese Anforderung, da auch bei einem Fehler ein gültiger Rückgabewert zurückgegeben wird.
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? */
}
}
Der obige Code basiert auf dem Verhalten von strtod()
Linux . Der C-Standard schreibt nur vor, dass der Unterlauf keinen Wert zurückgeben kann, der größer als das kleinste Positiv ist double
, und ob die errno
Einstellung ERANGE
festgelegt ist oder nicht, ist in der Implementierung definiert 2 .
Tatsächlich gibt es eine umfangreiche Beschreibung der Zertifizierungsempfehlungen, in der empfohlen wird errno
, vor einem Bibliotheksaufruf immer den Wert 0 festzulegen und den Wert nach dem Aufruf zu überprüfen, um anzuzeigen, dass ein Fehler aufgetreten ist . Dies liegt daran, dass einige Bibliotheksaufrufe auch dann gesetzt werden errno
, wenn der Aufruf selbst erfolgreich war 3 .
Der Wert von errno
ist beim Programmstart 0, wird jedoch von keiner Bibliotheksfunktion auf 0 gesetzt. Der Wert von errno
kann durch einen Bibliotheksfunktionsaufruf auf ungleich Null gesetzt werden, unabhängig davon, ob ein Fehler vorliegt oder nicht, vorausgesetzt, die Verwendung von errno
ist in der Beschreibung der Funktion im C-Standard nicht dokumentiert. Für ein Programm ist es sinnvoll, den Inhalt von errno
erst zu überprüfen, nachdem ein Fehler gemeldet wurde. Genauer gesagt errno
ist dies nur dann sinnvoll, wenn eine Bibliotheksfunktion, die errno
einen Fehler festlegt, einen Fehlercode zurückgegeben hat.
1. Früher habe ich behauptet, es sollte vermieden werden, einen Fehler aus einem früheren Anruf zu maskieren. Ich kann keine Beweise finden, die diese Behauptung stützen. Ich hatte auch ein falsches printf()
Beispiel.
2. Vielen Dank an @chux für diesen Hinweis. Referenz ist C.11 §7.22.1.3 ¶10.
3. In einem Kommentar von @KeithThompson darauf hingewiesen.
errno
, können Sie es jederzeit selbst auf Null setzen.