views:

162

answers:

3

Hello, when I run this program while inputting a number greater than 46348, I get a segmentation fault. For any values below it, the program works perfectly. I am using CodeBlocks 8.02 on Ubuntu 10.04 64-bit. The code is as follows:

int main()
{

    int number = 46348;
    vector<bool> sieve(number+1,false);
    vector<int> primes;
    sieve[0] = true;
    sieve[1] = true;

    for(int i = 2; i <= number; i++)
    {
        if(sieve[i]==false)
        {
            primes.push_back(i);
            int temp = i*i;
            while(temp <= number)
            {
                sieve[temp] = true;
                temp = temp + i;
            }
        }
    }

    for(int i = 0; i < primes.size(); i++)
        cout << primes[i] << " ";

    return 0;
}
+6  A: 

Assuming you are on a common architecture, the problem is that the i*i calculation overflows. The result can not be stored in a signed 32 bit integer. You can try adding cout << temp << endl; after this calculation. In the end it will print:

2144523481
2146190929
2147117569
-2146737495
Segmentation fault

For the future, you will want to run your code in a debugger. It lets you spot these things more easily. I suspect CodeBlocks offers a graphical debugger. (Otherwise, make sure to compile with -ggdb and run your program with gdb)


Since you are on a 64 bit platform, you might want to use 64 bits unsigned integers to get a greater range. unsigned long long (C99, C++0x) is a good way to ask for "the biggest int you've got, that's reasonably cheap". (Even though one long long might span two registers, as is the case with a 64 bit datatype on IA32)


Alternatively, you can add a check to automatically verify that number < sqrt(numeric_limits<int>::max()) before entering the loop.

Magnus Hoff
Thanks guys :D' It works great now!
rEgonicS
On many common 64 bit platforms, `unsigned long` is only 32 bit. `long long` has been a part of standard C for more than a decade now.
caf
@caf: Thanks. I've learned something new and updated my answer :)
Magnus Hoff
A: 

temp is a 32bit signed integer. In this line:

int temp = i*i;

it computes 46348*46348 = +2,148,137,104 (maximum value for an signed integer is +2,147,483,647) which creates an overflow (it becomes a negative number) and later you try to access the array with this result:

sieve[temp] = true;

By accessing the array with a negative number you get the segmentation fault.


(You could change it to unsigned int (maximum value +4,294,967,295)

Felix Kling
A: 

This line: int temp = i*i; causes temp to overflow when i is bigger than 46348, causing the sieve to look for a negative element. Segfault!

Replacing int by unsigned long long will allow you to go much further.

small_duck