问题
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