【问题标题】:Segmentation Fault C++ (array too large?)分段错误 C++(数组太大?)
【发布时间】:2014-09-28 00:17:19
【问题描述】:

我正在从事 Project Euler Problem 14,我需要在其中找到 1,000,000 以下的最长 collat​​z 序列。我提出了一种适用于较小数字(例如 100)的算法,它将 1 到 100 之间的每个 collat​​z 数字存储到一个数组中,并使用该数组作为参考来加快计算更大数字的速度。 我的代码如下:

#include <iostream>
using namespace std;

long even(long n){ //the even-collatz function
    n=n/2;
    return n;
}

long odd(long n){ //the odd collatz function
    n=3*n+1;
    return n;
}

int main(){
    long  x, c=0, y[1000000]; // x= the number we are finding the collatz number of, c a counter that keeps track of how many steps we've taken in the sequence, y is an array to store the collatz numbers.

    for (x=1; x<1000000; x++){ //iterates from x=1 to 1 million
            long a = x;     //sets a number a equal to the number we are currently trying to find the collatz number of
            long b = a;     
            c=0;                    //intializes counter at 0 
            while (a!=0){           //loops infinitely; the only way to exit is through a break.
                    if (a%2==0){    // detects if the number is even
                            a=even(a);      //applies the even-collatz function if so; sets x=x/2
                            c=c+1;
                            if (y[a]!=0){   // checks if the collatz number of x is already discovered
                                    y[b]=c+y[a]; //adds the current number of steps to the collatz number of x and 
                                    break;  //exits the while loop
                            }

                    }
                    else if (a==1){         //checks if the new x is equal to one and
                            y[b]=c;         //if it is, it writes the current value of c to y[b] and
                            break;          // exits the loop
                    }
                    else if (a%2==1){       //same as the "even" block, except for odd numbers 

                            a=odd(a);
                            c=c+1;
                            if( y[a]!=0){
                                    y[b]=c+y[a];
                                    break;
                            }

                    }
            //this is the end of the while loop; we've applied the collatz function as many times as we've needed to to x, and incremented the counter each time
            }
  }

    long z;
    for (int n=0;n!=100;n++){
            if (y[n+1]>y[n]){
                    z=y[n+1];
            }
    }
    cout << z << "\n";


}

我遇到的问题是在 for 循环中 x=1818 之后出现段错误。通过调试,我发现segfault发生的速度取决于数组y的大小,所以我假设数组太大了。根据我对段错误的(基本)理解,我认为我只是在访问“不允许”的内存。我有什么办法可以规避这个问题,还是我应该开始努力寻找解决这个问题的另一种方法?我在 Ubuntu studio 上使用 g++ 进行编译。

【问题讨论】:

    标签: c++ arrays segmentation-fault


    【解决方案1】:

    这个数组可能对于您系统的默认堆栈大小来说太大了;最简单的解决方法是将其定义更改为:

    std::vector<long> y(1000000);
    

    其他一切都可以保持不变。您可以稍后在循环中使用 y.size() 而不是幻数 1000000。

    【讨论】:

      【解决方案2】:

      对于N 下的起始编号,collat​​z 序列可以远远超出N。对于N == 1000000,请考虑x == 333335。

      我建议您将y 设为vector&lt;int&gt; 并动态扩展它,或者将其设为unordered_map&lt;int, int&gt;。

      【讨论】:

        【解决方案3】:

        如果 y 对你的堆栈来说太大了,你会在 main 尝试运行时得到堆栈溢出异常。

        您的问题更有可能是a 变得大于y 的大小。 当我通过调试器运行它时,a 是 1417174,而 x 是 4255,所以你的算法可能有问题。

        也就是说,您应该自己分配它,或者将其设为静态,因为无法保证 Project Euler 使用的任何编译器都允许如此大的堆栈大小。

        【讨论】:

        • 堆栈溢出导致许多平台出现分段错误。
        • @HevyLight 是的,但这并不取决于 x 有多大 - 只要运行函数,您就会得到异常。如果分段错误是由缓冲区溢出引起的,而不是堆栈溢出。
        猜你喜欢
        • 1970-01-01
        • 2018-08-15
        • 2020-06-08
        • 1970-01-01
        • 2019-09-30
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 2022-01-08
        相关资源
        最近更新 更多