问题
I am learning C++ from Algorithms in C++ by Robert Sedgewick. Right now I am working on the Sieve of Eratosthenes with a user specified upper bound on the largest prime. When I run the code with max 46349, it runs and prints out all primes up to 46349, however when I run the code with max 46350, a Segmentation fault occurs. Can someone help to explain why?
./sieve.exe 46349
2 3 5 7 11 13 17 19 23 29 31 ...
./sieve.exe 46350
Segmentation fault: 11
Code:
#include<iostream>
using namespace std;
static const int N = 1000;
int main(int argc, char *argv[]) {
int i, M;
//parse argument as integer
if( argv[1] ) {
M = atoi(argv[1]);
}
if( not M ) {
M = N;
}
//allocate memory to the array
int *a = new int[M];
//are we out of memory?
if( a == 0 ) {
cout << "Out of memory" << endl;
return 0;
}
// set every number to be prime
for( i = 2; i < M; i++) {
a[i] = 1;
}
for( i = 2; i < M; i++ ) {
//if i is prime
if( a[i] ) {
//mark its multiples as non-prime
for( int j = i; j * i < M; j++ ) {
a[i * j] = 0;
}
}
}
for( i = 2; i < M; i++ ) {
if( a[i] ) {
cout << " " << i;
}
}
cout << endl;
return 0;
}
回答1:
You have integer overflow here:
for( int j = i; j * i < M; j++ ) {
a[i * j] = 0;
}
46349 * 46349
does not fit in an int
.
On my machine, changing the type of j
to long
makes it possible to run the program for larger inputs:
for( long j = i; j * i < M; j++ ) {
Depending on your compiler and architecture, you may have to use long long
to get the same effect.
回答2:
When you run your program with a debugger, you will see that it fails at
a[i * j] = 0;
i * j
overflows and becomes negative. This negative number is less than M
, that's why it enters the loop once more and then fails on access to a[-2146737495]
.
回答3:
I see, the problem was declaring M as an int. When I declare i,M and j as long, this seems to work fine.
回答4:
In any reasonably modern C++, you will not get a null pointer back from new if the allocation fails unless you use a non-throwing new. That part of your code isn't going to work as you expect it to - you'll have to catch std::bad_alloc
that might be emitted from the call to new
instead.
You also want to declare your array indices as type size_t
.
来源:https://stackoverflow.com/questions/15177018/c-array-allocation-segmentation-fault-11-newbie