分段故障(核心转储)只有更大的输入

时间:2014-07-25 06:38:57

标签: c++ segmentation-fault core

如果seive(n)是1000000,我的代码可以正常工作。如果seive(n)超过10000000,它会显示我的分段错误(核心转储)。我已经阅读了有关分段错误的信息。但我无法解决这个问题。

    #include <stdio.h>
    #include <math.h>

    using namespace std;


    int seive(long int n)
    {
        long int A[n];

        for (long int i = 2; i <= n; i += 1)
        {
            A[i] = i;
        }
        long int root = (int)sqrt(n);

        for(int j = 2; j <= root; j++)
        {

            for(int k = 2*j; k < n ; k = k + j)
            {       
                A[k] = 0;
            }
        }
        int count = 0;
        for (int l = 2; l < n; ++l)
        {
            if(A[l] != 0) count++;
        }
        printf("%d\n", count);

    }

    int main()
    {
        seive( 1000000);
    }

3 个答案:

答案 0 :(得分:3)

  

long int A [n];

这是堆栈上的数组。如果N很大,它真的很大。你的堆栈不够大,无法在这种情况下保存它,你会收到堆栈溢出错误。

解决方案包括:

动态分配内存:long int * A =(long int *)malloc(n * sizeof(long int));

动态分配内存C ++样式:long int * A = new long int [n];

使用静态分配的缓冲区(当时不在堆栈上):static long int A [n];

使其全局化:将该行向上移动3行。

答案 1 :(得分:2)

你要做的是尝试在堆栈上分配一个包含大量元素的数组(堆栈内存)

long int A[n];

通常,您可以使用

在堆上分配更大的数组
int *A = new int[n]

答案 2 :(得分:2)

由于多种原因,您的自动存储空间在您的平台上超出其限制税。

首先,假设您的平台unsigned long int为64位,每个元素不必要地比它需要的大63位。筛子通常只需要代表两个值中的一个&#34; true&#34;或&#34;假&#34;。一个bool数组就足够了,可以对你的算法进行一些细微的调整。

其次,尽管第一项非常重要,但它并不是数组大小的主导因素。该特权属于n,是您的任务的最高限额。您在自动存储中请求了大量空间。假设您在平台上解决了第一个和bool的表示,只需一个字节,10000000条目的标志数组仍然需要大约。 9.54 MB的自动存储,这不是笑话。

解决方案是动态存储,可以通过多种方式完成,其中一些方法是:

  • 使用malloc(sizeof(bool)*(n+1))(在现代C ++程序中不鼓励)
  • 使用new bool[n+1]](更好,但仍然不是很好)
  • 使用像RAII这样的std::vector<bool>容器(现在我们正在某处)

采用以上内容的非常简单的抛出筛网示例如下所示。您可以使用关于偶数的优化逻辑(甚至不需要保留它们)来改进此显着,等等。但这不是重点。关键是使用动态存储,最好是具有自动生命周期的东西,std::vector<>很适合你。

#include <iostream>
#include <vector>
#include <cmath>
#include <cstdlib>

unsigned long int sieve(unsigned long int N)
{
    std::vector<bool> vec(N+1,true);
    unsigned long int res = 1;
    const unsigned long int SR = std::floor(std::sqrtl(static_cast<long double>(N)));

    for (unsigned long int i=2; i<=SR; ++i)
    {
        if (vec[i])
        {
            ++res;
            for (unsigned long int j=(i << 1); j<=N; j+=i)
                vec[j] = false;
        }
    }

    for (unsigned long int i=SR+1; i<=N; ++i)
    {
        if (vec[i])
            ++res;
    }
    return res;
}

int main()
{
    std::cout << sieve(10000000) << '\n';
    return 0;
}

<强>输出

664580

我认为这是正确的,除非你是那种无视1(有些人,不知道为什么)的人,在这种情况下它会被一个人拒绝。