当我input一个大于46348的数字的时候运行这个程序,我得到了一个分段错误。 对于任何低于它的值,该程序完美地工作。 我在Ubuntu 10.04 64位上使用CodeBlocks 8.02。 代码如下:
int main() { int number = 46348; vector<bool> sieve(number+1,false); vector<int> primes; sieve[0] = true; sieve[1] = true; for(int i = 2; i <= number; i++) { if(sieve[i]==false) { primes.push_back(i); int temp = i*i; while(temp <= number) { sieve[temp] = true; temp = temp + i; } } } for(int i = 0; i < primes.size(); i++) cout << primes[i] << " "; return 0; }
假设你在一个共同的架构上,问题是i*i
计算溢出。 结果不能存储在一个有符号的32位整数。 你可以尝试添加cout << temp << endl;
经过这个计算。 最后它会打印:
2144523481 2146190929 2147117569 -2146737495 Segmentation fault
将来,您将需要在调试器中运行您的代码。 它可以让你更容易地发现这些东西。 我怀疑CodeBlocks提供了一个图形化的调试器。 (否则,请确保使用-ggdb
编译并使用gdb
运行程序)
由于您位于64位平台上,因此您可能希望使用64位无符号整数来获得更大的范围。 unsigned long long
(C99,C ++ 0x)是一个很好的方法来要求“你得到的最大的int,这是相当便宜的”。 (即使一个long long
可能跨越两个寄存器,就像IA32上的64位数据类型一样)
或者,您可以添加一个检查以在进入循环之前自动验证number < sqrt(numeric_limits<int>::max())
。
temp
是一个32位有符号整数。 在这一行中:
int temp = i*i;
它计算46348*46348 = +2,148,137,104
(有符号整数的最大值是+2,147,483,647
),它会产生一个溢出(它变成一个负数),然后尝试访问这个结果的数组:
sieve[temp] = true;
通过访问与负数的数组,你会得到分段错误。
(你可以把它改成unsigned int
(最大值+4,294,967,295
)
这行:int temp = i * i; 当我大于46348时导致温度溢出,导致筛子寻找负面因素。 段错误!
用unsigned long long替换int可以让你更进一步。