我正在从Robert Sedgewick的C++算法中学习C++。现在,我正在研究Eratosthenes的筛子,在最大素数上有一个用户指定的上限。当我用最大值46349运行代码时,它运行并打印出直到46349的所有素数,但是当我用最大值46350运行代码时,出现了分段错误。有人能帮我解释一下原因吗?
./sieve.exe 46349
2 3 5 7 11 13 17 19 23 29 31 ...
./sieve.exe 46350
Segmentation fault: 11代码:
#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;
}发布于 2013-03-03 01:01:42
这里有整数溢出:
for( int j = i; j * i < M; j++ ) {
a[i * j] = 0;
}int中不适合使用46349 * 46349。
在我的机器上,将j的类型更改为long,这样就可以对更大的输入运行程序:
for( long j = i; j * i < M; j++ ) {根据您的编译器和体系结构,您可能必须使用long long才能获得相同的效果。
发布于 2013-03-03 01:05:21
当您使用调试器运行程序时,您将看到它在
a[i * j] = 0;i * j溢出并变为负值。这个负数小于M,这就是为什么它再次进入循环,然后在访问a[-2146737495]时失败。
发布于 2013-03-03 01:01:06
我明白了,问题是把M声明为int。当我声明i、M和j为long时,这似乎可以很好地工作。
https://stackoverflow.com/questions/15177018
复制相似问题