当我输入大于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;
}
答案 0 :(得分:7)
假设您使用的是通用架构,问题是i*i
计算溢出。结果不能存储在带符号的32位整数中。您可以尝试在此计算后添加cout << temp << endl;
。最后它将打印出来:
2144523481
2146190929
2147117569
-2146737495
Segmentation fault
将来,您需要在调试器中运行代码。它可以让您更轻松地发现这些东西。我怀疑CodeBlocks提供了一个图形调试器。 (否则,请务必使用-ggdb
进行编译,然后使用gdb
)
由于您使用的是64位平台,因此您可能需要使用64位无符号整数来获得更大的范围。 unsigned long long
(C99,C ++ 0x)是一个很好的方式来询问“你得到的最大的内容,这是相当便宜的”。 (即使一个long long
可能跨越两个寄存器,就像IA32上的64位数据类型一样)
或者,您可以添加一项检查,以便在进入循环之前自动验证number < sqrt(numeric_limits<int>::max())
。
答案 1 :(得分:1)
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
)
答案 2 :(得分:1)
这一行:int temp = i * i;当我大于46348时导致temp溢出,导致筛子寻找负面元素。段错误!
用unsigned long long替换int将使你更进一步。