带有Clang的C大数组中的奇怪分割错误

时间:2018-11-07 18:37:32

标签: c clang

在这里,我想找到200万以下的所有素数之和。 我使用Eratosthenes筛子,所以我需要200万个阵列。

起初,我只将数组声明为全局变量,但是zsh给我一个分段错误。所以我尝试了malloc,但错误仍然存​​在。 我已经测试了小型数组,程序运行正常。

此外,我使用clang-1000.10.44.2,使用-O2程序可以运行,但答案不正确。代码如下。

#include <stdio.h>
#include <stdlib.h>

#define MAXN 2000000

unsigned long long sum;
void erat(int maxn, char *flag)
{
    flag[0] = 0;
    flag[1] = 0;
    for(int i = 2; i < maxn; i++)
        if(flag[i])
            for(int j = i * i; j < maxn; j+=i)
                flag[j] = 0;
}

int main()
{
    int i;
    char *flag = (char*) malloc(MAXN * sizeof(char));
    for(i = 0; i < MAXN; i++)
        flag[i] = 1;
    erat(MAXN, flag);
    for(i = 0; i < MAXN; i++)
        if(flag[i]) sum+=i;
    printf("%llu\n", sum);
    return 0;
}

希望有人可以帮助我,谢谢您的宝贵时间!

2 个答案:

答案 0 :(得分:5)

i46349时,i*i2148229801,这比整数更合适,因此溢出到-2146737495,因为它小于maxnflag[j] = 0被执行,超出了数组的范围,因此崩溃。

j更改为long long可修复该错误:

for (long long j = (long long)i * i; j < maxn; j += i)

答案 1 :(得分:1)

您的int在这里溢出了:

for (int j = i * i; j < maxn; j+=i)

由于i达到2000000,所以i*i可能大于2 31 ,从而导致溢出和undefined behavior

您可以在外部循环中解决此问题:

for(int i = 2; i < maxn; i++)

您只需要检查maxn的平方根,因此将其更改为:

for(int i = 2; i * i < maxn; i++)