In Standard-C gibt es keinen portablen Weg, String-zu-Float-Fehler zu erkennen
No portable way to detect string-to-float conversion errors in standard C
Der Blogbeitrag zeigt, dass die Standard-C-Funktionen strtod, strtof und strtold Überlauf- und Unterlauf-Fehler nur dann über errno oder Floating-Point-Ausnahmen melden, wenn das Makro math_errhandling dies vorsieht. POSIX schreibt zwar immer errno vor, aber das ist möglicherweise nicht standardkonform. Bei ungültiger Eingabe setzt musl errno auf EINVAL, glibc nicht – ein undokumentierter Unterschied. Der Autor listet auf, wie man Fehler dennoch erkennt.
musl, on the other hand, does set errno to EINVAL, so this prints "22". This is completely undocumented on the linux man page.
- Joker_vD
Es ist ziemlich erstaunlich, wie die historische Unfähigkeit gängiger Programmiersprachen (von FORTRAN bis hin zu, sagen wir, Java/C#), ergonomisch zwei Werte aus einem Funktionsaufruf zurückzugeben, dazu geführt hat, dass Leute alle möglichen irrsinnigen APIs/Verträge erfunden haben.
[double x, errno_t errno] = strtod(s, nullptr);
if (errno != 0) {
// ...
}
[x, _] = strtod(s, nullptr); // Wenn man sicher ist, dass der Fehler unmöglich ist, oder es einem einfach egal ist
Stattdessen bleiben uns bestenfalls „prüfe, ob der Rückgabewert -1 ist, und wenn ja, prüfe die globale Variable errno“ und schlimmstenfalls „die Funktion meldet ihre Fehler nicht wirklich zuverlässig, also füttere sie nicht mit fehlerhaften Daten, mir doch egal“.
- Panzerschrek
Die C-Funktionen zum Parsen von Zahlen sind grundlegend kaputt, da sie locale-abhängig sind. Es gibt viele Bugs, wenn man eine Zahl parst und annimmt, sie habe einen Dezimalpunkt, aber später auf Systemen mit einem anderen Locale als dem des Entwicklers plötzlich ein Komma statt eines Punkts steht. Man sollte sie also fast immer vermeiden und std::from_chars (in neuen C++-Versionen verfügbar) oder eine andere Drittanbieter-Bibliothek verwenden.
- gucci-on-fleek
> die Linux-Manpages für diese Funktionen erwähnen das buchstäblich überhaupt nicht
> die Tatsache, dass die Manpage nie darauf hinweist, dass dies eine Erweiterung ist ([…]), ist für mich wirklich bemerkenswert.
> das ist auf der Linux-Manpage völlig undokumentiert.
Die Maintainer der Linux-Manpages sind meiner Erfahrung nach wirklich freundlich, also lohnt es sich wahrscheinlich, ihnen das zu melden [0] [1].
[0]: https://git.kernel.org/pub/scm/docs/man-pages/man-pages.git/...
- Kevin_Flynn
> Kein portabler Weg, String-zu-Float-Konvertierungsfehler in Standard-C zu erkennen
Es gibt nicht nur ein Standard-C, es gibt viele. Die KI sagt, es gibt 5.
Es gibt 5 große ISO-C-Standards: C90, C99, C11, C17/C18 und C23. C89 ist im Wesentlichen derselbe Standard wie C90 unter seinem ANSI-Namen, und C95 war eine Änderung und keine separate Hauptausgabe. Der neueste ist C23.
POSIX, wie du weißt, steht für „Portable Operating System Interface“.
> posix schert sich einen Dreck um math_errhandling; es verlangt immer, dass die Implementierung errno setzt, wenn Über- oder Unterlauf auftritt.
Also spezifiziert POSIX, das „portable“ Interface, dass Unterlauf-/Überlauffehler immer gemeldet werden.
Das Problem scheint in der Überschrift zu liegen, nicht in der Spezifikation.
- chasil
IEEE-754 ist eine harte Herrin.