素数筛分段故障

时间:2010-05-09 21:27:52

标签: c++ linux segmentation-fault

当我输入大于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;
}

3 个答案:

答案 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将使你更进一步。