Check for int overflow in C++ - c++

I'm running a C++ program which adds numbers in a for loop:
int y = 0;
for (int i=0; i<NUM; i++) {
int pow = 1;
for (int j=0 j<i; j++) {
pow *= 10;
}
y+= vec[i]*pow; // where vec is a vector of digits
}
but I am not sure how to check if an overflow has occured. Is there a way?

As Peter rightly explained, overflow is undefined behavior in standard C++11 (or C99), and you really should be afraid of UB.
However, some compilers give you extensions to deal and detect integer overflow.
If you can restrict yourself to a recent GCC compiler, you could use its integer overflow builtins.
You could also restrict yourself to int32_t and compute arithmetic in int64_t and check against result above INT32_MAX or below INT32_MIN. This would be probably slower (but more portable) than using compiler specific extensions. BTW some compilers also have some __int128_t type (so you could compute arithmetic in __int128_t and check likewise that the result fits in int64_t).
If your goal is to have arbitrary precision arithmetic, better use some exising bignum library, like GMPlib (because efficient bignum arithmetic needs very clever algorithms).

Overflow of a signed integral variable results in undefined behaviour. A consequence is that, once overflow has occurred, it cannot be reliably detected in standard C++. Any behaviour is permitted. So your implementation (compiler, library, toolset, etc) may provide a specific means to detect integer overflow - but that means will not necessarily work with other implementations.
The only ways are to check for potential overflows before doing operations (or a sequence of operations). Or to design your approach (e.g. pick limits) to prevent overflow occurring.

There are different options and probably no one that suits every situation and need.
For example in this situation you could check that if pow is less or equal to INT_MAX/10 before multiplying. This works because INT_MAX/10 is the largest number such that it times 10 will be at most INT_MAX. Note that the compiler would normally precompute the INT_MAX/10 if you insert it into the code (otherwise you could put it in a local variable if it bothers you):
int y = 0;
for (int i=0; i<NUM; i++) {
int pow = 1;
for (int j=0 j<i; j++) {
if( pow > INT_MAX/10 )
throw OverflowException;
pow *= 10;
}
y+= vec[i]*pow; // where vec is a vector of digits
}
This solution has the disadvantage that if the other factor is not constant the compiler (and you) can't reasonably avoid the division INT_MAX/n to be done at runtime (and division is normally more expensive than multiplication).
Another possibility is that you could do the calculation in a wider type. For example:
int y = 0;
for (int i=0; i<NUM; i++) {
int32_t pow = 1;
for (int j=0 j<i; j++) {
int64_t tmp = (int64_t)pow * (int64_t)10;
if( tmp > (int64_t)INT32_MAX )
raise OverflowException;
pow = (int32_t)tmp;
}
y+= vec[i]*pow; // where vec is a vector of digits
}
This have the disadvantage that first a wider type might not be available, and if it is it may require software implementation of the multiplication (for example 64-bit on 32-bit systems) which means slower multiplication.
Another situation is where you add two integers. If overflow occurs the result will be less than both integers, especially if they're both positive the result will be negative.

Related

Using `size_t` for lengths impacts on compiler optimizations?

While reading this question, I've seen the first comment saying that:
size_t for length is not a great idea, the proper types are signed ones for optimization/UB reasons.
followed by another comment supporting the reasoning. Is it true?
The question is important, because if I were to write e.g. a matrix library, the image dimensions could be size_t, just to avoid checking if they are negative. But then all loops would naturally use size_t. Could this impact on optimization?
size_t being unsigned is mostly an historical accident - if your world is 16 bit, going from 32767 to 65535 maximum object size is a big win; in current-day mainstream computing (where 64 and 32 bit are the norm) the fact that size_t is unsigned is mostly a nuisance.
Although unsigned types have less undefined behavior (as wraparound is guaranteed), the fact that they have mostly "bitfield" semantics is often cause of bugs and other bad surprises; in particular:
difference between unsigned values is unsigned as well, with the usual wraparound semantics, so if you may expect a negative value you have to cast beforehand;
unsigned a = 10, b = 20;
// prints UINT_MAX-10, i.e. 4294967286 if unsigned is 32 bit
std::cout << a-b << "\n";
more in general, in signed/unsigned comparisons and mathematical operations unsigned wins (so the signed value is casted to unsigned implicitly) which, again, leads to surprises;
unsigned a = 10;
int b = -2;
if(a < b) std::cout<<"a < b\n"; // prints "a < b"
in common situations (e.g. iterating backwards) the unsigned semantics are often problematic, as you'd like the index to go negative for the boundary condition
// This works fine if T is signed, loops forever if T is unsigned
for(T idx = c.size() - 1; idx >= 0; idx--) {
// ...
}
Also, the fact that an unsigned value cannot assume a negative value is mostly a strawman; you may avoid checking for negative values, but due to implicit signed-unsigned conversions it won't stop any error - you are just shifting the blame. If the user passes a negative value to your library function taking a size_t, it will just become a very big number, which will be just as wrong if not worse.
int sum_arr(int *arr, unsigned len) {
int ret = 0;
for(unsigned i = 0; i < len; ++i) {
ret += arr[i];
}
return ret;
}
// compiles successfully and overflows the array; it len was signed,
// it would just return 0
sum_arr(some_array, -10);
For the optimization part: the advantages of signed types in this regard are overrated; yes, the compiler can assume that overflow will never happen, so it can be extra smart in some situations, but generally this won't be game-changing (as in general wraparound semantics comes "for free" on current day architectures); most importantly, as usual if your profiler finds that a particular zone is a bottleneck you can modify just it to make it go faster (including switching types locally to make the compiler generate better code, if you find it advantageous).
Long story short: I'd go for signed, not for performance reasons, but because the semantics is generally way less surprising/hostile in most common scenarios.
That comment is simply wrong. When working with native pointer-sized operands on any reasonable architectute, there is no difference at the machine level between signed and unsigned offsets, and thus no room for them to have different performance properties.
As you've noted, use of size_t has some nice properties like not having to account for the possibility that a value might be negative (although accounting for it might be as simple as forbidding that in your interface contract). It also ensures that you can handle any size that a caller is requesting using the standard type for sizes/counts, without truncation or bounds checks. On the other hand, it precludes using the same type for index-offsets when the offset might need to be negative, and in some ways makes it difficult to perform certain types of comparisons (you have to write them arranged algebraically so that neither side is negative), but the same issue comes up when using signed types, in that you have to do algebraic rearrangements to ensure that no subexpression can overflow.
Ultimately you should initially always use the type that makes sense semantically to you, rather than trying to choose a type for performance properties. Only if there's a serious measured performance problem that looks like it might be improved by tradeoffs involving choice of types should you consider changing them.
I stand by my comment.
There is a simple way to check this: checking what the compiler generates.
void test1(double* data, size_t size)
{
for(size_t i = 0; i < size; i += 4)
{
data[i] = 0;
data[i+1] = 1;
data[i+2] = 2;
data[i+3] = 3;
}
}
void test2(double* data, int size)
{
for(int i = 0; i < size; i += 4)
{
data[i] = 0;
data[i+1] = 1;
data[i+2] = 2;
data[i+3] = 3;
}
}
So what does the compiler generate? I would expect loop unrolling, SIMD... for something that simple:
Let's check godbolt.
Well, the signed version has unrolling, SIMD, not the unsigned one.
I'm not going to show any benchmark, because in this example, the bottleneck is going to be on memory access, not on CPU computation. But you get the idea.
Second example, just keep the first assignment:
void test1(double* data, size_t size)
{
for(size_t i = 0; i < size; i += 4)
{
data[i] = 0;
}
}
void test2(double* data, int size)
{
for(int i = 0; i < size; i += 4)
{
data[i] = 0;
}
}
As you want gcc
OK, not as impressive as for clang, but it still generates different code.

Why c++ STL uses unsigned in size() funtion? [duplicate]

This question already has answers here:
size_t vs int in C++ and/or C
(9 answers)
Closed 4 years ago.
I have encountered a problem while I was using a loop like this,
//vector<int> sides;
for (int i = 0; i < sides.size()-2; i++) {
if (sides[i] < sides[i+1] + sides[i+2]) {
...
}
}
The problem was that the size() method uses an unsigned number. So, vectors of size less than 2 make an undefined outcome.
I understand that I should have used an unsigned variable for the loop but it doesn't solve the problem. So I had to deal with it by typecasting or using some conditions.
My question is that why do STL uses an unsigned int to eliminate negative index access violation and generating more problems?
It was decided that containers would use unsigned indexes and sizes way back in the 90s.
On the surface this seemed wise; I mean, sizes and indexes into containers cannot be negative. It also permits slightly larger max values, especially on 16 bit systems.
It is now considered a mistake; your code is but one of the many reasons why. std2 will almost certainly use ptrdiff_t, the signed partner of size_t, for sizes and indexes.
Note that 1u-2 is defined behaviour; it is -1 cast to unsigned, which is guaranteed to be the max unsigned value of that type.
You can fix your code in many ways, including:
for (int i = 0; i+2 < sides.size(); i++) {
if (sides[i] < sides[i+1] + sides[i+2]) {
or
for (int i = 0; i < (std::ptrdiff_t)sides.size()-2; i++) {
if (sides[i] < sides[i+1] + sides[i+2]) {
this second one can break on containers near the size of your memory space limit; on 64 bit systems this is not a problem, on 32 bit systems and vectors of char there is a slim chance you could create a vector large enough.
The reason is that the operator sizeof that determines the size of any object returns a value of the type size_t. So for example also the standard C functiuon strlen has return type size_t.
As result it is adopted that standard containers also returns their sizes as values of the type size_t.
As for the loop then it can be rewritten for example the following way
for ( size_t i = 0; i + 2 < sides.size(); i++) {
if (sides[i] < sides[i+1] + sides[i+2]) {
...
}
}

Is it safe to use == on FP in this example

I stumbled onto this code here.
Generators doubleSquares(int value)
{
Generators result;
for (int i = 0; i <= std::sqrt(value / 2); i++) // 1
{
double j = std::sqrt(value - std::pow(i, 2)); // 2
if (std::floor(j) == j) // 3
result.push_back( { i, static_cast<int>(j) } ); // 4
}
return result;
}
Am I wrong to think that //3 is dangerous ?
This code is not guaranteed by the C++ standard to work as desired.
Some low-quality math libraries do not return correctly rounded values for pow, even when the inputs have integer values and the mathematical result can be exactly represented. sqrt may also return an inaccurate value, although this function is easier to implement and so less commonly suffers from defects.
Thus, it is not guaranteed that j is exactly an integer when you might expect it to be.
In a good-quality math library, pow and sqrt will always return correct results (zero error) when the mathematical result is exactly representable. If you have a good-quality C++ implementation, this code should work as desired, up to the limits of the integer and floating-point types used.
Improving the Code
This code has no reason to use pow; std::pow(i, 2) should be i*i. This results in exact arithmetic (up to the point of integer overflow) and completely avoids the question of whether pow is correct.
Eliminating pow leaves just sqrt. If we know the implementation returns correct values, we can accept the use of sqrt. If not, we can use this instead:
for (int i = 0; i*i <= value/2; ++i)
{
int j = std::round(std::sqrt(value - i*i));
if (j*j + i*i == value)
result.push_back( { i, j } );
}
This code only relies on sqrt to return a result accurate within .5, which even a low-quality sqrt implementation should provide for reasonable input values.
There are two different, but related, questions:
Is j an integer?
Is j likely to be the result of a double calculation whose exact result would be an integer?
The quoted code asks the first question. It is not correct for asking the second question. More context would be needed to be certain which question should be being asked.
If the second question should be being asked, you cannot depend only on floor. Consider a double that is greater than 2.99999999999 but less than 3. It could be the result of a calculation whose exact value would be 3. Its floor is 2, and it is greater than its floor by almost 1. You would need to compare for being close to the result of std:round instead.
I would say it is dangerous. One should always test for "equality" of floating point numbers by comparing the difference between the two numbers with an acceptably small number, e.g.:
#include <math.h>
...
if (fabs(std::floor(j) - j) < eps) {
...
... where eps is a number that is acceptably small for one's purpose. This approach is essential unless one can guarantee that the operations return exact results, which may be true for some cases (e.g. IEEE-754-compliant systems) but the C++ standard does not require that this be true. See, for instance Cross-Platform Issues With Floating-Point Arithmetics in C++.

Binary Addition without overflow wrap-around in C/C++

I know that when overflow occurs in C/C++, normal behavior is to wrap-around. For example, INT_MAX+1 is an overflow.
Is possible to modify this behavior, so binary addition takes place as normal addition and there is no wraparound at the end of addition operation ?
Some Code so this would make sense. Basically, this is one bit (full) added, it adds bit by bit in 32
int adder(int x, int y)
{
int sum;
for (int i = 0; i < 31; i++)
{
sum = x ^ y;
int carry = x & y;
x = sum;
y = carry << 1;
}
return sum;
}
If I try to adder(INT_MAX, 1); it actually overflows, even though, I amn't using + operator.
Thanks !
Overflow means that the result of an addition would exceed std::numeric_limits<int>::max() (back in C days, we used INT_MAX). Performing such an addition results in undefined behavior. The machine could crash and still comply with the C++ standard. Although you're more likely to get INT_MIN as a result, there's really no advantage to depending on any result at all.
The solution is to perform subtraction instead of addition, to prevent overflow and take a special case:
if ( number > std::numeric_limits< int >::max() - 1 ) { // ie number + 1 > max
// fix things so "normal" math happens, in this case saturation.
} else {
++ number;
}
Without knowing the desired result, I can't be more specific about the it. The performance impact should be minimal, as a rarely-taken branch can usually be retired in parallel with subsequent instructions without delaying them.
Edit: To simply do math without worrying about overflow or handling it yourself, use a bignum library such as GMP. It's quite portable, and usually the best on any given platform. It has C and C++ interfaces. Do not write your own assembly. The result would be unportable, suboptimal, and the interface would be your responsibility!
No, you have to add them manually to check for overflow.
What do you want the result of INT_MAX + 1 to be? You can only fit INT_MAX into an int, so if you add one to it, the result is not going to be one greater. (Edit: On common platforms such as x86 it is going to wrap to the largest negative number: -(INT_MAX+1). The only way to get bigger numbers is to use a larger variable.
Assuming int is 4-bytes (as is typical on x86 compilers) and you are executing an add instruction (in 32-bit mode), the destination register simply does overflow -- it is out of bits and can't hold a larger value. It is a limitation of the hardware.
To get around this, you can hand-code, or use an aribitrarily-sized integer library that does the following:
First perform a normal add instruction on the lowest-order words. If overflow occurs, the Carry flag is set.
For each increasingly-higher-order word, use the adc instruction, which adds the two operands as usual, but takes into account the value of the Carry flag (as a value of 1.)
You can see this for a 64-bit value here.

Cast from size_t to int, or iterate with size_t?

Is it better to cast the iterator condition right operand from size_t to int, or iterate potentially past the maximum value of int? Is the answer implementation specific?
int a;
for (size_t i = 0; i < vect.size(); i++)
{
if (some_func((int)i))
{
a = (int)i;
}
}
int a;
for (int i = 0; i < (int)vect.size(); i++)
{
if (some_func(i))
{
a = i;
}
}
I almost always use the first variation, because I find that about 80% of the time, I discover that some_func should probably also take a size_t.
If in fact some_func takes a signed int, you need to be aware of what happens when vect gets bigger than INT_MAX. If the solution isn't obvious in your situation (it usually isn't), you can at least replace some_func((int)i) with some_func(numeric_cast<int>(i)) (see Boost.org for one implementation of numeric_cast). This has the virtue of throwing an exception when vect grows bigger than you've planned on, rather than silently wrapping around to negative values.
I'd just leave it as a size_t, since there's not a good reason not to do so. What do you mean by "or iterate potentially up to the maximum value of type_t"? You're only iterating up to the value of vect.size().
For most compilers, it won't make any difference. On 32 bit systems, it's obvious, but even on 64 bit systems, both variables will probably be stored in a 64-bit register and pushed on the stack as a 64-bit value.
If the compiler stores int values as 32 bit values on the stack, the first function should be more efficient in terms of CPU-cycles.
But the difference is negligible (although the second function "looks" cleaner)