Segmentation fault while checking size of bitset

眉间皱痕 提交于 2021-02-05 09:28:11

问题


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
}

回答1:


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.




回答2:


You are not guaranteed to segfault when you mess up a reference or fencepost! The behavior is "undefined", and can be quite troublesome to track down. Use something like 'valgrind' to find the exact first moment of badness.



来源:https://stackoverflow.com/questions/25861003/segmentation-fault-while-checking-size-of-bitset

易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!