Das erste Code-Snippet ist einfach falsch, und ich werde später erklären, warum, aber zuerst brauchen wir etwas Hintergrund.
errno
ist eine thread-local Variable. Es wird auf einen Wert ungleich Null gesetzt, wenn ein Systemaufruf oder bestimmte Bibliotheksfunktionen fehlschlagen. Es bleibt unverändert, wenn ein Systemaufruf erfolgreich ist. Es enthält also immer die Fehlernummer vom letzten fehlgeschlagenen Aufruf.
Dies bedeutet, dass Sie zwei Möglichkeiten haben. Setzen Sie entweder errno
vor jedem Anruf auf 0, oder verwenden Sie das Standard-Idiom für errno
. Hier ist der Pseudo-Code für die Standard-Idiom
if (foo() == some_value_that_indicates_that_an_error_occurred)
then the value in errno applies to foo
else
foo succeeded and the errno must be ignored because it could be anything
Die meisten Programmierer die Standard-Idiom verwenden, weil Einstellung errno
-0 vor jedem Systemaufruf ist ärgerlich, sich wiederholend, sich wiederholend, ärgerlich und lästig repetitiv. Ganz zu schweigen von der Tatsache, dass Sie vielleicht vergessen, errno
auf 0 an der einen Stelle zu setzen, die wirklich zählt.
Zurück zum ersten Code-Snippet. Es ist falsch, weil es keinen Rückgabewert von strtol
gibt, der eindeutig anzeigt, dass strtol
fehlgeschlagen ist. Wenn strtol
LONG_MAX
zurückgibt, konnte es sein, dass ein Fehler aufgetreten ist, oder die Zeichenfolge enthielt tatsächlich die Nummer LONG_MAX
. Es gibt keine Möglichkeit zu wissen, ob der strtol
Aufruf erfolgreich war oder fehlgeschlagen ist. Dies bedeutet, dass das Standard-Idiom (das der erste Codeausschnitt zu implementieren versucht) nicht mit strtol
verwendet werden kann.
strtol
richtig nutzen zu können, müssen Sie errno
-0 vor dem Aufruf setzen, wie dieser
errno = 0;
result = strtol(buffer, &endptr, 10);
if (errno == ERANGE)
{
// handle the error
// ERANGE is the only error mentioned in the C specification
}
else if (endptr == buffer)
{
// handle the error
// the conversion failed, i.e. the input string was empty,
// or only contained whitespace, or the first non-whitespace
// character was not valid
}
Beachten Sie, dass einige Implementierungen andere Werte ungleich Null für errno
definieren. Weitere Informationen finden Sie auf der entsprechenden Manpage.
Es ist schwer zu sagen durch den begrenzten Kontext, den Sie uns gegeben haben. –
Ich habe noch nie eine gute Erklärung dafür gefunden, warum es notwendig ist, nach 'LONG_MAX/LONG_MIN' und' ERANGE' zu suchen. Abgesehen davon, dass die Manpage das als Beispiel zeigt. Der einzige vernünftige Anwendungsfall, den ich mir vorstellen kann, ist die Unterscheidung zwischen Überlauf und Unterlauf. Ich wäre auch interessiert zu hören, ob es andere Gründe gibt. – kaylum
@ kaylum Ich weiß nicht, dass mein Beispiel richtig ist, weil ich nicht unterscheiden möchte, ob ein Überlauf oder Unterlauf aufgetreten ist und dass errno in beiden Fällen auf ERANGE gesetzt ist. Wenn einer von ihnen aufgetreten ist, ist das Ergebnis ungültig. –