问题出在UBA清洗器将负双精度数强制转换为无符号长长整数上。

huangapple go评论75阅读模式
英文:

Issue with UBA sanitizer casting negative double to unsigned long long on C++

问题

我一直在使用C++,并且一直在使用UBA sanitizer将double转换为unsigned long long。然而,当值为负数时,我遇到了一个问题,导致错误消息:“运行时错误:值-2超出了类型'long long unsigned int'可表示值的范围。”

代码大致如下:

unsigned long long valueULL = 0;
double value = -2;
valueULL = (unsigned long long)value;

我尝试使用这个强制转换,但没有帮助:

valueULL = std::make_unsigned_t(value);

是否有一种方法可以在不遇到此错误的情况下进行强制转换?

英文:

I've been working with C++ and have been utilizing the UBA sanitizer to convert a double to an unsigned long long. However, I've been encountering an issue when the value is negative, which results in the error message: "runtime error: value -2 is outside the range of representable values of type 'long long unsigned int'"

The code is something like this:

unsigned long long valueULL = 0;
double value = -2;
valueULL = (unsigned long long)value;

I tried to use this cast instead and it doesn't help:

valueULL = std::make_unsigned_t<unsigned long long>(value);

Is there a way to cast it without encountering this error?

答案1

得分: 1

看起来你正在提到clang的-fsanitize=undefined UBSanitizer。
在这种情况下,这个检测器是正确的,你的代码确实包含未定义行为:

浮点类型的prvalue可以转换为整数类型的prvalue。
这个转换会截断,即舍弃小数部分。
如果截断后的值无法表示为目标类型,行为将是未定义的。

  • [conv.fpint] §1

你可以通过两步转换来修复未定义行为:

double value = -2;
auto valueULL = static_cast<unsigned long long>(static_cast<long long>(value));

或者,你可以调用std::llround

auto valueULL = static_cast<unsigned long long>(std::llround(value));

注意:这将产生一个非常大的值,即ULLONG_MAX - 2。如果这正是你想要的,那么这些解决方案是有意义的。
否则,你应该听从检测器的建议,并确保在转换为unsigned类型之前,你的double不会变成负数。

英文:

It seems that you're referring to clang's -fsanitize=undefined UBSanitizer.
The sanitizer is correct in this case, and your code really does contain undefined behavior:

> A prvalue of a floating-point type can be converted to a prvalue of an integer type.
The conversion truncates; that is, the fractional part is discarded.
The behavior is undefined if the truncated value cannot be represented in the destination type.

- [conv.fpint] §1

You can fix your undefined behavior with a two-step cast:

double value = -2;
auto valueULL = static_cast&lt;unsigned long long&gt;(static_cast&lt;long long&gt;(value));

Or alternatively, you could call std::llround:

auto valueULL = static_cast&lt;unsigned long long&gt;(std::llround(value));

Note: this will produce a very great value, namely ULLONG_MAX - 2. If this is what you actually want, then these solutions make sense.
Otherwise, you should listen to the sanitizer and make sure that your double doesn't turn negative before converting to unsigned types.

huangapple
  • 本文由 发表于 2023年6月22日 12:55:45
  • 转载请务必保留本文链接:https://go.coder-hub.com/76528707.html
匿名

发表评论

匿名网友

:?: :razz: :sad: :evil: :!: :smile: :oops: :grin: :eek: :shock: :???: :cool: :lol: :mad: :twisted: :roll: :wink: :idea: :arrow: :neutral: :cry: :mrgreen:

确定