C++浮点转整型竟会触发未定义行为
C++ float-to-int conversion can be undefined behavior
在C++中,将float转换为int时,若截断后的值超出目标整数范围,就会触发未定义行为。这种错误极易发生,且编译器默认不会发出警告。即便是Microsoft的Guidelines Support Library(GSL)中的gsl::narrow函数,也未能正确处理此类情况,反而在特定输入下产生未定义行为。尽管当前硬件和编译器可能让程序‘看似正常’,但不同平台上的表现差异可能导致严重问题。正确的做法是在转换前进行边界检查。作者基于Rust的饱和处理思路,开发了一个概念验证库cpp-clamp-cast,并推荐使用Clang和GCC的Undefined Behavior Sanitizer(-fsanitize=float-cast-overflow)来检测此类问题。
你的程序没有崩溃,并不意味着问题不存在;不同硬件上的不同结果才是真正麻烦的根源。
HN 评论区
17- digitalPhonix
Herb Sutter 关于“为什么这样做没问题”的评论让我很困惑:
> 关于内部使用未定义行为(UB):这是可以的,如果有人担心,在我们针对的平台上,这种 UB 是无害的(例如,它不会触发这些类型的任何硬件陷阱表示)。
未定义行为的结果(即它是会执行“rm -rf /”还是其他什么)难道不是同时取决于目标平台和编译器吗?而且编译器(或未来的编译器)完全有可能做出假设,认为缩窄到一个不可阻止的值永远不会发生,并因此改变行为?
- pjmlp
希望这能成为 C++29 中未定义行为修复的一部分,届时大量未定义行为将被重新定义为错误行为。
- orangepanda
如果结果在 ARM 和 x86 上都不一样,那怎么可能被定义为定义良好的行为呢?