为什么我的筛子得到了SIGSEGV

时间:2014-10-12 17:33:11

标签: c math

好吧,所以,为了好玩,我正在研究eratosthenes的筛子。 它工作得很好,所以我试图提高它的运行时复杂性。而现在,我不知道为什么,但我是一个分段错误。 这是代码:

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

int main(void)
{
    int* check = malloc(1000000000 * sizeof(int));
    long long int i;
    for(i = 0;i < 1000000000;i++)
    {
        check[i] = 0;
    }
    int j = 0;
    for(i = 2;i <= 1000000002;i++)
    {
         if(check[i] == 0)
         {
            printf("%lld\n", i);
            for(j = 1;j < (1000000001/i);j++)
            {
                check[j*i] == 1;
            }
         }
    }
return 0;   
}

任何有关失败原因的帮助都将不胜感激。

2 个答案:

答案 0 :(得分:0)

您的代码有多个错误,其中任何错误都可以解释段错误。首先,您尚未检查malloc的返回值,即使您完全确定它不是NULL,也可能是i

其次,当你将Initial allocation: 1,000,000,000 Range of i: 2 to 1,000,000,002 inclusive 从2迭代到1000000002时,你超出了你分配的数组的范围。有这么多的零,很难看出来,所以这里有你的数字用分隔符:

{{1}}

在该循环结束时,您将访问数组末尾的内存。

答案 1 :(得分:0)

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

#if 1
static const size_t N = 1000 * 1000 * 1000;
#else
static const size_t N = 1000;
#endif

不要使用幻数,将其定义为常量。 1000000000也难以阅读。您的C编译器可以在发出可执行文件之前为您进行计算。而且你应该从一小部分开始。如果您将#if 1更改为#if 0,那么将#else定义为1,000的N子句将生效。

int main(void)
{
    char* check = malloc(N + 3);

当您基本上使用check作为布尔数组时,它不必是int类型。 int占用4个字节,而char仅占1个字节。

    if (NULL == check) {
        perror("malloc");
        abort();
    }

malloc在找不到指定长度的内存块时无声地返回NULL。但是如果你使用64位操作系统和编译器,我认为它不会失败......

    long long int i;
    memset(check, 0, sizeof(check[0]) * (N + 3));

memset使用第二个参数的值填充数组(此处为0。)第三个参数采用输入数组的BYTES数,因此我使用了sizeof(check[0])(这个对于char数组而言,sizeof(char)==1不是必需的,但我始终坚持这种做法。)

    int j = 0;
    for(i = 2;i <= N+2;i++)
    {
         if(check[i] == 0)
         {
            printf("%lld\n", i);
            for(j = 1;j < ((N+1)/i);j++)
            {
                check[j*i] = 1;

你写了check[j*i] == 1,但这是一个相等的测试,其结果没有任何影响。

            }
         }
    }
    free(check);

最好始终free使用malloc分配的内存块,无论是否需要free(在这种情况下不是,因为您的程序刚刚退出)在筛子计算结束时。)也许直到你真正流利的C。

return 0;   
}