I have a legacy codebase which we are trying to migrate from devtoolset-4
to devtoolset-7
. I noticed an interesting behaviour regarding overflow of signed integers (int64_t
, to be specific).
There is a code snippet which is used to detect integer overflow while multiplying a big set of integers:
// a and b are int64_t
int64_t product = a * b;
if (b != 0 && product / b != a) {
// Overflow
}
This code was working fine with devtoolset-4. However, with devtoolset-7, overflow is never being detected.
For eg: When a = 83802282034166
and b = 98765432
, the
product
becomes -5819501405344925872
(clearly the value has overflown).
But product / b
results in value equal to a (83802282034166)
. Hence the if
condition never becomes true.
Its value should have been computed based on the overflown (negative) product
value: -5819501405344925872 / 98765432 = -58922451788
Ironically, the Maths is correct but it is causing anomalous behaviour with regards to devtoolset-4.
- Could the compiler be caching the value (and not re-evaluating it) resulting in this behaviour?
- Or does compiler optimization converts statement
product / b != a
toproduct != a * b
and reaches the same overflown value (or maybe just skips the computation based on the above statement whereproduct = a * b
)?
I understand that signed integer overflow is an 'undefined behaviour' in C++ and so the compiler behaviour could change across implementations. But could someone help me make sense of the above behaviour?
Note: the g++ versions in devtoolset-4 and devtoolset-7 are g++ (GCC) 5.2
and g++ (GCC) 7.2.1
, respectively.