Segfault while looping - c++

Working through a simple problem, but getting a segmentation fault because the program is writing past the end of the array.
#include <iostream>
#include <stdio.h>
static const int N = 46350;
int main()
{
int* intarray = new int[N];
for (int i = 2; i < N; ++i)
{
intarray[i] = 1;
}
for (int i = 2; i < N; ++i)
{
if (intarray[i])
{
for (int j = i; j*i < N; ++j)
{
printf("before i: %i j: %i ", i, j);
std::cout << "a: " << intarray + i*j << std::endl;
intarray[i*j] = 0;
printf("after i: %i j: %i ", i, j);
std::cout << "a: " << intarray + i*j << std::endl;
}
}
}
delete [] intarray;
return 0;
}
Console output:
before i: 211 j: 219 array: 0x21dd24c
after i: 211 j: 219 array: 0x21dd24c
before i: 46349 j: 46349 array: 0x2488aec
This doesn't happen for N = 46349. Not sure what's going on.

Integer overflow is causing this. The product of i and j overflows the range of type int and produces a negative value, which obviously compares as "less than N". Later you attempt to modify memory at that negative index i * j, which leads to unpredictable results. In fact, the overflow itself is already producing undefined behavior.
For this value of N you can get away with using unsigned int type instead of int type. The former has two times larger positive range. But in general case you have to remember that a product of two int value does not necessarily fit into the range of int type.
In your case i can become as large as 46349 and 46349 * 46349 = 2148322500, which is greater than the typical upper limit of signed 2's-complement 32-bit integer 2147483647.
The version with N=463549 is formally also broken in the very same way, except that you got lucky with that version. The if (intarray[i]) check prevents the inner cycle from running in situations where it would lead to overflow.

The maximum integer (int) in your case is 2^31-1, which is 2147483647. The square root of that number is 46340.95... So when you multiply i * j you are getting an integer overflow, the result looks negative, and it appears to be < N and is allowed through in the loop. So you get a fault. So really, anything above 46340 and you could have some problems.

Related

Why are variable length arrays in C++ overlapping on some sizes?

After providing an answer to a question here, I was testing this code that I edited and noticed some strange behavior:
#include <iostream>
#define MAX 100
using namespace std;
int main()
{
int size = 0;
int array[MAX];
int i, j;
int input;
cout << "Array: ";
for(i = 0; i < MAX; i++)
{
cin >> input;
if(input == -1)
break;
else
{
array[i] = input;
size++;
}
}
cout << "Size: " << size << "\n\n";
int left[size / 2];
int right[size / 2];
for(i = 0; i < size / 2; i++)
left[i] = array[i];
for(i = size / 2, j = 0; i < size; i++, j++)
right[j] = array[i];
cout << "Left: ";
for(i = 0; i < size / 2; i++)
cout << left[i] << ' ';
cout << '\n';
cout << "Right: ";
for(i = 0; i < size - size / 2; i++)
cout << right[i] << ' ';
cout << '\n';
return 0;
}
This code is supposed to split the array into two separate arrays. Somehow the output is wrong when these are the input:
1 2 3 4 5 6 7 8 9 -1
Left: 9 2 3 4
Right: 5 6 7 8 9
After debugging If the elements of left were printed like this:
for(i = size / 2, j = 0; i < size; i++, j++)
{
right[j] = array[i];
cout << left[0] << ' ';
}
cout << '\n';
It says that the value of left[0] is modified after the 5th iteration:
1 1 1 1 9
Left: 9 2 3 4
Right: 5 6 7 8 9
This only happens when the array size is 9. I haven't tested beyond 16 yet. I could fix the code so that it would have the correct size
int right[size - size / 2];
or use malloc() to adhere to the C++ Standard,
int *left = (int *) malloc(sizeof(*left) * n / 2);
int *right = (int *) malloc(sizeof(*left) * n / 2);
so that left wouldn't be affected, but that's not what I'm asking. Why does it only happen when splitting an array size of 9? Why was left[0] overwritten? Is this is a bug in g++ that should be reported or is the problem something else?
It says that the value of left[0] is modified after the 5th iteration:
That is your answer. The problem occurs in the fifth iteration over an array with four elements.
When size is odd, the calculation of size/2 rounds down. So the sum size/2 + size/2 is strictly less than size, yet your loops ensure that all size elements from the original array are assigned somewhere. Something has to be assigned to an unexpected location. We call this "undefined behavior", and whatever the compiler does at that point is correct according to the C++ standard. (Whatever happens, the compiler gets to blame your code for it.) It just happens that when size is 9, the compiler used left[0] as the location for right[4].
Behind the scenes, the left and right arrays are probably more-or-less adjacent in memory. The layout would have right[0] through right[size/2], then possibly some unused space (also known as "padding"), then left[0] through left[size/2]. When you access one-past the last element of right, you end up either in the unused space or in left[0]. When you overwrite the unused space, you see no symptoms since that space is otherwise unused. However, when you overwrite left[0] you definitely see a symptom.
Your compiler apparently uses padding to make sure the arrays are aligned to 4*sizeof(int). (Must be faster that way, as compilers rarely introduce waste without a reason. Still, I am surprised it's not 2*sizeof(int) instead.) That is, there is no padding when size/2 is a multiple of 4. If this guesswork is accurate, you should see this behavior when size is odd and size/2 is a multiple of 4; that is when size is one more than a multiple of 8, as in 9, 17, 25, 33, etc.

what does int numbers[n+2]; statement do?

#include<iostream>
int fastFibonacci(int n)
{
int numbers[n+2]; // int numbers[n].
numbers[0] = 0;
numbers[1] = 1;
for (int i = 2; i <= n; i++)
{
numbers[i] = numbers[i - 1] + numbers[i - 2];
}
return numbers[n];
}
int main() {
int n;
std::cout << "Enter a Number";
std::cin >> n;
int result = fastFibonacci(n);
std::cout << result << "\n";
return 0;
}
in this code when i enter input 0 or 1 get correct answer. But the problem is that when i replace int numbers[n+2]; with the commented part it start giving me wrong answer when input is 0 or 1. why? anyone please explain me.
In this function
int fastFibonacci(int n)
{
int numbers[n+2]; // int numbers[n].
numbers[0] = 0;
numbers[1] = 1;
for (int i = 2; i <= n; i++)
{
numbers[i] = numbers[i - 1] + numbers[i - 2];
}
return numbers[n];
}
there is used a variable length array with n + 2 elements declared in this line
int numbers[n+2]; // int numbers[n].
Variable length arrays is not a standard C++ feature. It can be implemented as own language extension of a C++ compiler.
Using the variable length array makes the function very unsafe because there can occur a stack overflow.
As within the function there is explicitly used two elements of the array
numbers[0] = 0;
numbers[1] = 1;
then the array shall have at least two elements even when the parameter has a value less than 2.
To calculate the n-th Fibonacci number there is no need to declare an array of such a size.
Apart from this the function argument shall have an unsigned integer type. Otherwise the function can invoke undefined behavior if the user passes a negative number.
Also for big values of n there can be an integer overflow for the type int.
The function can be implemented in various ways.
Here is one of possible its implementations.
#include <iostream>
#include <functional>
unsigned long long fibonacci( unsigned int n )
{
unsigned long long a[] = { 0, 1 };
while ( n-- )
{
a[1] += std::exchange( a[0], a[1] );
}
return a[0];
}
int main()
{
const unsigned int N = 10;
for ( unsigned int i = 0; i < N; i++ )
{
std::cout << i << ": " << fibonacci( i ) << '\n';
}
return 0;
}
The program output is
0: 0
1: 1
2: 1
3: 2
4: 3
5: 5
6: 8
7: 13
8: 21
9: 34
int numbers[n+2]; is the declaration of an array of ints with space for n + 2 ints, this is a variable lenght array and is not part of C++ standard, though some compilers allow it it's not somenthing you should use.
If you need a variable lenght array use std::vector.
With int numbers[n+2]; if n is equal to 0 you still have space for 2 ints, if you have int numbers[n]; the array will have space for 0 ints, so the code will fail because you are trying to access memory that does not exist with numbers[0] and numbers[1].
There are several good ways to implement the Fibonacci sequence, in the site you can find many questions regarding this matter in several programming languages, here is one of them Fibonacci series in C++
Edit
So I've seen your comments about using a vector, for making the sequence you wouldn't need the vector just two variables to store the two numbers to add, to store the sequence in a vactor, you can do somenthing like:
#include <iostream>
#include <vector>
#include <iomanip>
//passing the vector by reference
void fastFibonacci(unsigned long long n, std::vector<unsigned long long>& sequence) {
unsigned long long first = 0;
unsigned long long second = 1;
sequence.push_back(first); //add first values to the vector
sequence.push_back(second); //add first values to the vector
for (unsigned long long i = 0, value = 0; i < n && value <= LLONG_MAX ; ++i) {
value = first + second;
first = second;
second = value;
sequence.push_back(value); //adding values to the vector
}
}
int main() {
unsigned long long limit; //number of values in the sequence
int num = 1;
std::vector<unsigned long long> sequence; //container for the sequence
std::cout << "Enter upper limit: ";
std::cin >> limit;
fastFibonacci(limit, sequence);
//print the sequence in a range based loop formatted with <iomanip> library
for(auto& i : sequence){
std::cout << std::setw(4) << std::left << num++ << " " << i << std::endl;
}
return 0;
}
If you want to print just one of the numbers in the sequence, just use, for instance:
std::cout << sequence[10];
Instead of the whole vector.
The code you post in the comment to the other answer won't work because the access to the vector is out of bounds in numbers[i] = numbers[i - 1] + numbers[i - 2];, if for instance i = 5, your vector only has 2 nodes but you are accessing the 6th node numbers[5].

C++ - Digitwise addition with carryover for arbitrary unsigned ints - running into memory problems [duplicate]

I have made some research on Stackoverflow about reverse for loops in C++ that use an unsigned integer instead of a signed one. But I still do NOT understand why there is a problem (see Unsigned int reverse iteration with for loops). Why the following code will yield a segmentation fault?
#include <vector>
#include <iostream>
using namespace std;
int main(void)
{
vector<double> x(10);
for (unsigned int i = 9; i >= 0; i--)
{
cout << "i= " << i << endl;
x[i] = 1.0;
}
cout << "x0= " << x[0] << endl;
return 0;
}
I understand that the problem is when the index i will be equal to zero, because there is something like an overflow. But I think an unsigned integer is allowed to take the zero value, isn't it? Now if I replace it with a signed integer, there is absolutely no problem.
Does somebody can explain me the mechanism behind that reverse loop with an unsigned integer?
Thank you very much!
The problem here is that an unsigned integer is never negative.
Therefore, the loop-test:
i >= 0
will always be true. Thus you get an infinite loop.
When it drops below zero, it wraps around to the largest value unsigned value.
Thus, you will also be accessing x[i] out-of-bounds.
This is not a problem for signed integers because it will simply go negative and thus fail i >= 0.
Thus, if you want to use unsigned integers, you can try one of the following possibilities:
for (unsigned int i = 9; i-- != 0; )
and
for (unsigned int i = 9; i != -1; i--)
These two were suggested by GManNickG and AndreyT from the comments.
And here's my original 3 versions:
for (unsigned int i = 9; i != (unsigned)0 - 1; i--)
or
for (unsigned int i = 9; i != ~(unsigned)0; i--)
or
for (unsigned int i = 9; i != UINT_MAX; i--)
The problem is, your loop allows i to be as low as zero and only expects to exit the loop if i is less than 0. Since i is unsigned, it can never be less than 0. It rolls over to 2^32-1. That is greater than the size of your vector and so results in a segfault.
Whatever the value of unsigned int i it is always true that i >= 0 so your for loop never ends.
In other words, if at some point i is 0 and you decrement it, it still stays non-negative, because it contains then a huge number, probably 4294967295 (that is 232-1).
The problem is here:
for (unsigned int i = 9; i >= 0; i--)
You are starting with a value of 9 for an unsigned int and your exit definition is i >= 0 and this will be always true. (unsigned int will never be negative!!!). Because of this your loop will start over (endless loop, because i=0 then -1 goes max uint).
As you said a decrease of an unsigned below zero, which happens right after the last step of the loop, creates an overflow, the number wraps around to its maximum value and thus we end up with an infinite loop.
Does somebody can explain me the mechanism behind that reverse loop with an unsigned integer?
My preferred method for a reverse loop with an index is this:
for (unsigned int i = 9; i > 0; --i) {
cout << "i= " << x[i - 1] << endl;
}
and that is why because it maps most closely to the normal loop equivalent:
for (unsigned int i = 0; i < 9; ++i) {
cout << "i= " << x[i] << endl;
}
If then you need to access the indexed element multiple times and you don't want to continuously write [i - 1], you can add something like this as the first line in the loop:
auto& my_element = my_vector[i - 1];

strange behavior in for loop - a bug?

I'm working with Visual Studio 2012 on a Windows 7 machine and when trying to run the following code snippet (compiled with the default VC11 C++ compiler in x64 mode) the assertion fails, which means, that the inner loop is never entered:
void loopTest1()
{
const unsigned int k = 1;
for (int m=0; m<3; ++m)
{
int acc = 0;
for (int n=m-k; n<=m+k; ++n)
{
if (n<0 || n>=3) continue;
++acc;
}
assert (acc>0);
cout << "acc: " << acc << endl;
}
}
Now I change the inner loop's end condition:
void loopTest2()
{
const unsigned int k = 1;
for (int m=0; m<3; ++m)
{
int acc = 0;
int l = m+k; // this line was added
for (int n=m-k; n<=l; ++n) // m+k was replaced by l
{
if (n<0 || n>=3) continue;
++acc;
}
assert (acc>0);
cout << "acc: " << acc << endl;
}
}
Then I get the correct result:
acc: 2
acc: 3
acc: 2
When I replace the const unsigned int k by a hard-coded 1, it works, too:
void loopTest3()
{
//const unsigned int k = 1;
for (int m=0; m<3; ++m)
{
int acc = 0;
for (int n=m-1; n<=m+1; ++n) //replaced k with 1
{
if (n<0 || n>=3) continue;
++acc;
}
assert (acc>0);
cout << "acc: " << acc << endl;
}
}
Does the compiler perform some false optimizations?
Or is there any specific reason, why the behavior in the first case is at least unexpected?
Your int m is going to be promoted to an unsigned int. On the first loop, that means m-k is equal to -1 as an unsigned value, which is the maximum unsigned value and obviously greater than m+k (when n is compared, it gets promoted). To put it in perspective, you'll end up with n being an unsigned representation of -1 and m+k being 1. Of course when you store that -1 unsigned into a signed integer, it overflows and is technically undefined behaviour. It's most likely keeping its -1 representation and then being promoted back to a max unsigned value.
Here's a summary of sorts of the first iteration:
Iteration 1:
m: 0
k: 1u
n=m-k: -1u = max uint, stored into signed int
m+k: 1u
n<=m+k --> max uint <= 1u
In your second example, n is not promoted when compared to the other signed integer and it compares two signed integers. In your third, nothing is unsigned.

Unsigned integers in C++ for loops

I have made some research on Stackoverflow about reverse for loops in C++ that use an unsigned integer instead of a signed one. But I still do NOT understand why there is a problem (see Unsigned int reverse iteration with for loops). Why the following code will yield a segmentation fault?
#include <vector>
#include <iostream>
using namespace std;
int main(void)
{
vector<double> x(10);
for (unsigned int i = 9; i >= 0; i--)
{
cout << "i= " << i << endl;
x[i] = 1.0;
}
cout << "x0= " << x[0] << endl;
return 0;
}
I understand that the problem is when the index i will be equal to zero, because there is something like an overflow. But I think an unsigned integer is allowed to take the zero value, isn't it? Now if I replace it with a signed integer, there is absolutely no problem.
Does somebody can explain me the mechanism behind that reverse loop with an unsigned integer?
Thank you very much!
The problem here is that an unsigned integer is never negative.
Therefore, the loop-test:
i >= 0
will always be true. Thus you get an infinite loop.
When it drops below zero, it wraps around to the largest value unsigned value.
Thus, you will also be accessing x[i] out-of-bounds.
This is not a problem for signed integers because it will simply go negative and thus fail i >= 0.
Thus, if you want to use unsigned integers, you can try one of the following possibilities:
for (unsigned int i = 9; i-- != 0; )
and
for (unsigned int i = 9; i != -1; i--)
These two were suggested by GManNickG and AndreyT from the comments.
And here's my original 3 versions:
for (unsigned int i = 9; i != (unsigned)0 - 1; i--)
or
for (unsigned int i = 9; i != ~(unsigned)0; i--)
or
for (unsigned int i = 9; i != UINT_MAX; i--)
The problem is, your loop allows i to be as low as zero and only expects to exit the loop if i is less than 0. Since i is unsigned, it can never be less than 0. It rolls over to 2^32-1. That is greater than the size of your vector and so results in a segfault.
Whatever the value of unsigned int i it is always true that i >= 0 so your for loop never ends.
In other words, if at some point i is 0 and you decrement it, it still stays non-negative, because it contains then a huge number, probably 4294967295 (that is 232-1).
The problem is here:
for (unsigned int i = 9; i >= 0; i--)
You are starting with a value of 9 for an unsigned int and your exit definition is i >= 0 and this will be always true. (unsigned int will never be negative!!!). Because of this your loop will start over (endless loop, because i=0 then -1 goes max uint).
As you said a decrease of an unsigned below zero, which happens right after the last step of the loop, creates an overflow, the number wraps around to its maximum value and thus we end up with an infinite loop.
Does somebody can explain me the mechanism behind that reverse loop with an unsigned integer?
My preferred method for a reverse loop with an index is this:
for (unsigned int i = 9; i > 0; --i) {
cout << "i= " << x[i - 1] << endl;
}
and that is why because it maps most closely to the normal loop equivalent:
for (unsigned int i = 0; i < 9; ++i) {
cout << "i= " << x[i] << endl;
}
If then you need to access the indexed element multiple times and you don't want to continuously write [i - 1], you can add something like this as the first line in the loop:
auto& my_element = my_vector[i - 1];