20

After performing a mathematical operation, for say, multiplying two integers, is it possible to access the overflow flag register in a CPU with C++ ? If not what are other fast ways to check for an overflow ?

animuson
  • 53,861
  • 28
  • 137
  • 147
Loers Antario
  • 1,611
  • 6
  • 20
  • 24
  • 2
    Check this http://stackoverflow.com/questions/199333/best-way-to-detect-integer-overflow-in-c-c – acrilige Jan 16 '13 at 12:52
  • @acrilige thanks ,, that answers the second part of my question, any idea on how to check for the overflow AFTER performing the calculations ? – Loers Antario Jan 16 '13 at 12:56
  • For obvious reasons it is impossible to directly access the overflow flag register in a standard, portable way. However, you can determine if an operation will overflow with a little work, and there are ways to check this or detect overflows in a non-standard non-portable way. – Robert Mason Jan 16 '13 at 12:57
  • 1
    Why can't you check for overflow before calculations? – acrilige Jan 16 '13 at 12:58
  • Divide the result by the multiplicand. If you don't get the multiplier back then it overflowed. – Hans Passant Jan 16 '13 at 13:30

5 Answers5

16

No, generally it's impossible. Some CPUs don't even have such a flag (e.g. MIPS).

The link provided in one of the comments will give you ideas on how you can do overflow checks.

Remember that in C and C++ signed integer overflows cause undefined behavior and legally you cannot perform overflow checks after the fact. You either need to use unsigned arithmetic or do the checks before arithmetic operations.

Community
  • 1
  • 1
Alexey Frunze
  • 61,140
  • 12
  • 83
  • 180
9

I recommend this reading in every appropriate case. From Optimizing software in C++ -

Integer overflow is another security problem. The official C standard says that the behavior of signed integers in case of overflow is "undefined". This allows the compiler to ignore overflow or assume that it doesn't occur. In the case of the Gnu compiler, the assumption that signed integer overflow doesn't occur has the unfortunate consequence that it allows the compiler to optimize away an overflow check. There are a number of possible remedies against this problem: (1) check for overflow before it occurs, (2) use unsigned integers - they are guaranteed to wrap around, (3) trap integer overflow with the option -ftrapv, but this is extremely inefficient, (4) get a compiler warning for such optimizations with option -Wstrict-overflow=2, or (5) make the overflow behavior well-defined with option -fwrapv or -fno-strict-overflow.

SChepurin
  • 1,814
  • 25
  • 17
3

You'd have to do the operation and check the overflow bit in inline assembly. You could do that and jump to a label on overflow, or (more generally but less efficiently) set a variable if it overflowed.

T Percival
  • 8,526
  • 3
  • 43
  • 43
  • 1
    It's odd to me no one else mentioned this option. While inline assembly isn't strictly c++, it's absolutely a viable option for anyone who's asking this question. There is of course, the limitation that it won't compile for all architectures, but that's up to the OP to decide if that is important or not. – Joseph Summerhays Jul 15 '21 at 13:23
1

This is probably not what you want to do for two reasons:

  1. not every CPU has an overflow flag
  2. using C++ there is actually no way to access the overflow flag

the overflow checking tips that people have posted before might be useful.

if you really want to very write fast code that multiplies two integers and checks the overflow flag, you will have to use assembly. if you want some examples for x86, then do ask

abhoriel
  • 103
  • 1
  • 5
1

No. Best approach to check in advance as here

If not what are other fast ways to check for an overflow ?

If you need to test after operation you can use floating point representation (double precision) - every 32-bit integer can be represented exactly as floating point number. If all of the machines you target support IEEE (which is probably the case if you don't have to consider mainframes), you can just do the operations, then use isfinite or isinf on the results. Fast (in terms of programmer's efforts) way is: The IEEE Standard for Floating-Point Arithmetic (IEEE 754) defines five exceptions, each of which returns a default value and has a corresponding status flag that (except in certain cases of underflow) is raised when the exception occurs. The five possible exceptions are:

  • Invalid operation: mathematically undefined, e.g., the square root of a negative number. By default, returns qNaN.
  • Division by zero: an operation on finite operands gives an exact infinite result, e.g., 1/0 or log(0). By default, returns ±infinity.
  • Overflow: a result is too large to be represented correctly (i.e., its exponent with an unbounded exponent range would be larger than emax). By default, returns ±infinity for the round-to-nearest modes (and follows the rounding rules for the directed rounding modes).
  • Underflow: a result is very small (outside the normal range) and is inexact. By default, returns a subnormal or zero (following the rounding rules).
  • Inexact: the exact (i.e., unrounded) result is not representable exactly. By default, returns the correctly rounded result.
Vlad
  • 1,977
  • 19
  • 44
  • 1
    Note that this question is tagged [tag:integer-overflow] and is about signed-integer overflow. Not FP overflow to +-Inf. You *can* access FP flags via `fenv`: https://en.cppreference.com/w/c/numeric/fenv. `fetestexcept(FE_OVERFLOW)` checks the FP overflow flag. (Only works right if you use `#pragma STDC FENV_ACCESS ON` or command line options for some compilers. https://en.cppreference.com/w/c/numeric/fenv/fetestexcept has an example.) – Peter Cordes Apr 12 '20 at 18:42
  • I see - every integer can be represent as floating point number and there is no other fast ways. Except checking in advance. – Vlad Apr 12 '20 at 22:11
  • `double` can represent every `int32_t` but not every `int64_t`. So yes, you could check the range of a `double` before converting back to `int`. That's hardly efficient so IDK what your point is. Some machines will have an 80-bit or wider `long double` that can represent every `int64_t`, but many C++ implementations only have 64-bit FP. Also, FP overflow is irrelevant to this problem (unless you do multiple multiplies that actually produce FP overflow). – Peter Cordes Apr 12 '20 at 22:19
  • floating point number with double precision is limited by 10^308. More than 10^64. IEEE 754 is about single and double precision. – Vlad Apr 12 '20 at 22:26
  • Yes that's the highest finite `double`, but the first non-representable integer-valued `double` is 2^53 + 1 because it has a 53-bit mantissa. https://en.wikipedia.org/wiki/Double-precision_floating-point_format. A 64-bit `double` can represent some numbers other than possible values of `int64_t`, therefore by the pigeonhole principle there must be some values of `int64_t` that don't have a `double` bit pattern to represent them. See [Which is the first integer that an IEEE 754 float is incapable of representing exactly?](https://stackoverflow.com/q/3793838) – Peter Cordes Apr 12 '20 at 22:34
  • Likely you are write. Then this approach may be used for 32bit ints. Strange - my guess was that in C# conversion from any integral number including 64 bit is implicitly converted to double. And implicit conversion relates only to cast without loss of information. But you notice about mantissa likely correct - there should be gaps in representation - lost of precision – Vlad Apr 12 '20 at 22:39
  • Definitely you are write: The pigeonhole principle can be extended to sets by phrasing it in terms of cardinal numbers: if the cardinality of set L is greater than the cardinality of set D, then there is no injection from L to D. 2) Both double and long long (int64_t) has 2^64 states. Let L is set of possible int64_t long values and D is set of possible double values (not NaN). Some states in double is used for signaling values - so cardinality of L is greater then cardinality of D and there is no injection from L to D. – Vlad Apr 12 '20 at 23:18
  • Yup, besides signalling NaNs, `double` has lots of non-integer values as well. Half of the `double` bit patterns represent values between -1.0 and +1.0, and there are many fractional values between the smaller integers. (FYI, the English word you're looking for here is "right", not "write". Pronounced the same, spelled differently.) I didn't invent this proof just now; this is a well known fact. But glad I could help and point it out to you. Anyway, you might like https://randomascii.wordpress.com/2012/02/25/comparing-floating-point-numbers-2012-edition/ - great series of FP articles – Peter Cordes Apr 13 '20 at 00:13
  • Thanks-good article. I remember about (0..1) - for proof it's sufficient to mention different cardinality. Also I was afraid my C# book has error: "Implicit conversions are allowed when both of the following are true: 1) The compiler can guarantee they will always succeed. 2) No information is lost in conversion". But I didn't notice the book has note in footer: "A minor caveat is that very large long values lose some precision when converted to double... This is because floating-point types always have more magnitude than integral types, but may have less precision." So the book is right. – Vlad Apr 13 '20 at 01:21