C / C ++ Stackoverflow错误,数组为100万

时间:2011-12-07 15:46:59

标签: c++ arrays visual-studio-2010 stack-overflow

我正在使用VC ++ 2010.我编写了一个简短的程序,以便在长整数数组中获得100万个数字的Collat​​z猜想链,并获得最高的数字序列。当我尝试运行代码时,我得到堆栈溢出异常。

我应该如何解决这个问题?

//Might have took un-needed headers
#include "stdafx.h"
#include "stdio.h"
#include "conio.h"
#include "iostream"
#include "fstream"
#include "string"
#include "list"
using namespace std;


//traverse the array for max term 
long int max_array(long int a[], long int num_elements)
{
    long int i, max=-32000;
    for (i=0; i<num_elements; i++)
    {
        if (a[i]>max)
        {
            max=a[i];
        }
    }
    return(max);
}

//recursive function to calculate and count based on Collatz_conjecture
long int Collatz( long int c1, long int currentcounter)
{
    if ( c1 == 1) return currentcounter;
    if ( c1 % 2 ==0)
    {
        currentcounter++;
        Collatz (c1/2, currentcounter);
    }
    else
    {
        currentcounter++;
        Collatz((3*c1)+1, currentcounter);
    }
}

void main()
{   
    long int  totalcounter[1000000]={0},t1,max;

    for (long  int i=1;i<1000001;i++)
    {
        totalcounter[i]++;
        totalcounter[i]=Collatz(i,totalcounter[i]); 
        printf("Collatz count of no: %li is %li \n",i,totalcounter[i]);
    }
    max = max_array(totalcounter, 1000000);
    printf("The max is %d\n", max);
}

3 个答案:

答案 0 :(得分:3)

堆栈内存由自动变量和递归函数调用消耗。你使用大量的两者。

您可以使用迭代(Way to go from recursion to iteration)替换递归,并且可以使用堆分配的自变量(巨型数组)替换(使用new)。

这两件事都应该对你有所帮助。只需确保当你使用堆积分配堆栈的Collat​​z功能的迭代方法时,你就不会再遇到同样的问题了!

答案 1 :(得分:2)

堆栈通常是固定的,相当小的大小 - 可能是几兆字节。您正在做两件容易导致堆栈使用过多的事情:

  • 创建几兆字节的自动数组
  • 调用递归函数,递归深度没有界限;除非编译器能够将函数优化为循环,否则每个递归调用都会创建一个新的堆栈帧,因此如果Collat​​z路径太长,您将耗尽堆栈。

第一个可以通过使用计数器的动态数组来修复:

std::vector<long int> totalcounter;

或者不存储所有结果,只是每次迭代后找到的最大结果。

第二个可以通过检查编译器是否优化递归或者迭代实现来修复;这样的事情(未经测试):

long int Collatz(long int c1)
{
    long int counter = 0;
    while (c1 != 1) {
        ++counter;
        c1 = (c1 % 2 == 0) ? c1/2 : 3*c1+1;
    }
    return counter;
}

(如果您决定保留递归实现,那么您需要通过引用传递currentcounter,或者使用每个递归调用的返回值更新它,并记住在所有情况下都返回一个值此外,main()中的数组索引应该从0运行到N-1,而不是从1Nmain()必须返回{ {1}},但如果您愿意,可以省略int语句。

答案 2 :(得分:1)

在为大量数字计算Collat​​z链时,你会溢出long int。我认为这就是你的递归函数出错的原因。尝试将c1参数更改为64位类型,例如long long

我刚试过这个,当你达到值704511时,链的范围高达56991483520.顺便说一下,这是Project Euler问题14。

编辑:

将数组totalcounter[]的声明移到main()函数之外,使其成为全局变量。对于堆栈上的自动存储来说,它太大了(~4MB)。其他替代方案是动态分配数组或使用std::vector

您的代码工作示例here