C++ float-to-int conversion is undefined behavior and GSL's narrow() gets it wrong
C++ float-to-int conversion can be undefined behavior
Converting a float to an int in C++ is undefined behavior when the truncated value doesn't fit the destination type, yet compilers often don't warn. Even Microsoft's Guidelines Support Library (GSL) — which provides gsl::narrow() for safe narrowing — fails to handle this case, instead relying on benign UB. The author demonstrates the issue, explains why relying on hardware behavior is dangerous, and offers a proof-of-concept library plus UBSan detection.
Your code could suddenly stop working when the compiler happens to apply a different transformation.
- digitalPhonix
Herb Sutter's comment on why it's ok is confusing to me:
> Regarding the use of UB internally: It's okay and if anyone is worried about it the use of UB is benign on the platforms we target (e.g., they don't involve hitting any hardware trap representations for these types)
Isn't the outcome of the UB (ie. whether it will "rm -rf /" or something else) dependent on both the target and the compiler? And the compiler (or future compiler) could plausibly make the assumption that the narrowing to an unpreventable value will never occur and change behaviour because of it?
- pjmlp
Hopefully this will be part of UB fixes for C++29, where plenty of UB is being redefined as erroneous behaviour instead.
- orangepanda
How could it be defined behaviour, when the result is different on ARM and x86?