c++cubsan

Outside the range of representable values when casting double to long long with UBSAN enabled


Compiling the code below with UBSAN enabled causes this error:

Runtime error: value 9.22337e+18 is outside the range of representable values of type 'long long'

double a = (double)LLONG_MAX; // or (double)LLONG_MAX - 1
long long b = (long long)a;

Is this a known issue? My understanding is that the value is not outside the range.


Solution

  • What you are seeing is expected behavior.

    LLONG_MAX is a 64-bit integer on your system, needs 63 bits to fully represent its value (since one bit is used to hold the sign). A typical double (using IEEE arithmetic) only has 53 bits of precision.

    When you assign an integer to a double, the integer value needs to be converted to a double. When the integer needs more bits to represent its value than the double can store, this conversion will result in a loss of some of the precision of the value, which is accomplished thru rounding. It is an implementation detail if this will round up or round down, but under IEEE arithmetic rules the rounding will be to nearest.

    Because on your system the long value is rounded up, the resulting double value cannot be stored in a long long, resulting in your runtime error.