Search code examples
c++segmentation-faultbitset

Segmentation fault while checking size of bitset


I get a segmentation fault when I try to run the code below. I've tried commenting out bits of the code, and found that the while loop with the condition j < is_prime.size() is the culprit. This is puzzling to me because I perform the same check between the same values in the for loop above it, but do not get a segmentation fault.

Could someone explain to me what's the issue here?

I'm using GCC 4.8.2 on Linux 64.

#include <bitset>
#include <iostream>
using namespace std;

const size_t max_pandigital = 987654321;

int main()
{
    bitset<max_pandigital/3> is_prime;
    is_prime.set();                  // assume all numbers are prime
    is_prime[0] = false;             // 1 is not prime
    for(size_t i = 1; i < is_prime.size(); i++) {
        if(is_prime[i]) {
            int n;
            if(i%2 == 0) n = 3*i+1;
            else n = 3*i+2;
            size_t j = i;
            if(j%2 == 0) j += n-2;
            else j += n+2;
            while(j < is_prime.size()) {
                is_prime[j] = false;
                if(j%2 == 0) j += n-2;
                else j += n+2;
            }
        }
    }
    //cout << is_prime[899809363/3] << endl;
}

Edit: I implemented some of the changes suggested. Here's a working version - runs in ~13s. I think the biggest bottleneck is allocating the 42MB for the bool vector. Thanks!

#include <iostream>
#include <vector>
using namespace std;

const size_t max_pandigital = 987654321;

int main()
{
    vector<bool> not_prime(max_pandigital/3);
    not_prime[0] = true;             // 1 is not prime
    for(size_t i = 1; i < not_prime.size(); i++) {
        if(~not_prime[i]) {
            int n;
            if(i%2 == 0) n = 3*i+1;
            else n = 3*i+2;
            size_t j = i;
            if(j%2 == 0) j += n-2;
            else j += n+2;
            while(j < not_prime.size()) {
                not_prime[j] = true;
                if(j%2 == 0) j += n-2;
                else j += n+2;
            }
        }
    }
    cout << not_prime[899809363/3] << endl; // prime
    cout << not_prime[100017223/3] << endl; // pseudoprime
}

Solution

  • If the commented-out is commented in, and I run your code then I get a segfault due to stack overflow. (Even if the code remains commented out though, the stack still overflowed, which explains what you are seeing).

    Typical systems default to a stack size on the order of 1 megabyte; but your bitset requires about 40 megabytes of storage.

    To fix this you could either:

    • dynamically allocate your bitset
    • use a different container such as vector<bool>
    • tell your environment to use a larger stack size

    An example of dynamic allocation might be:

    unique_ptr< bitset<max_pandigital/3> > ip { new bitset<max_pandigital/3> };
    auto &is_prime = *ip;
    

    and the rest of the code the same.