简体   繁体   English

Segmentation Fault C ++(数组太大?)

[英]Segmentation Fault C++ (array too large?)

I'm working on the Project Euler Problem 14 , where I need to find the longest collatz sequence under 1,000,000. 我正在研究项目Euler 问题14 ,在这里我需要找到1,000,000以下最长的collat​​z序列。 I've come up with an algorithm that works for smaller numbers (say, 100) that stores each collatz number from 1 - 100 into an array and uses that array as a reference to speed up the computations for higher numbers. 我想出了一种适用于较小数字(例如100)的算法,该算法将1-100中的每个collat​​z数字存储到一个数组中,并使用该数组作为参考来加快较高数字的计算速度。 My code is as follows: 我的代码如下:

#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";


}

The issue I'm having is that I get a segfault after x=1818 in the for loop. 我遇到的问题是在for循环中x = 1818之后出现了段错误。 Through debugging, I've found that how quickly the segfault occurs depends on the size of array y, so I'm assuming that the array is just too big. 通过调试,我发现段错误发生的速度取决于数组y的大小,因此我假设数组太大。 From my (basic) understanding of segfaults, I think I'm just accessing memory that I'm "not allowed". 从对段错误的(基本)理解上,我认为我只是在访问“不被允许”的内存。 Is there any way for me to circumvent this, or should I just start working towards another solution to this problem? 我有什么办法可以解决这个问题,还是我应该开始着手解决这个问题的另一种方法? I'm compiling using g++ on Ubuntu studio. 我正在Ubuntu Studio上使用g ++进行编译。

This array is probably too big for your system's default stack size; 对于您系统的默认堆栈大小,此数组可能太大。 the simplest fix is to change its definition to: 最简单的解决方法是将其定义更改为:

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

and everything else can stay the same. 其他一切都可以保持不变。 You could use y.size() instead of the magic number 1000000 later in your loop. 您可以在循环中稍后使用y.size()而不是幻数1000000

For a starting number under N collatz sequence can go way beyond N . 对于N下的起始数字,collat​​z序列可以超出N For N == 1000000 consider x == 333335 . 对于N == 1000000考虑x == 333335

I would suggest you to make y a vector<int> and expand it dynamically, or just make it unordered_map<int, int> . 我建议您将y设为vector<int>并动态扩展它,或者只是使其变为unordered_map<int, int>

If y was too big for your stack, you would get a stack overflow exception as soon as main tried to run. 如果y对于您的堆栈太大,则在main尝试运行时,您将获得堆栈溢出异常。

Your problem is more likely that a gets bigger than the size of y . 您的问题很可能是a大于y的大小。 When I ran it through the debugger, a was 1417174 when x was 4255, so you might have a problem with your algorithm. 当我通过调试器运行它时,当x为4255时, a为1417174,因此您的算法可能有问题。

That said, you should either allocate it yourself, or make it static, as there is no guarantee that whatever compiler Project Euler uses will allow such a large stack size. 就是说,您应该自己分配它,或者使其静态,因为无法保证Euler项目使用的任何编译器都将允许如此大的堆栈大小。

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM