C/C++ 100 万数组中的 Stackoverflow 错误
我正在使用 VC++ 2010。我编写了一个简短的程序来获取长整型数组中 100 万个数字的 Collatz 猜想链,并获取系列中的最高数字。当我尝试运行代码时,出现堆栈溢出异常。
我该如何度过这个难关?
//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);
}
I am using VC++ 2010. I have written a short program to get Collatz conjecture chain for 1 million numbers in an long int array and get the highest number in series. When I try to run the code, I get stack overflow exception.
How should I get past this?
//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);
}
如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。
绑定邮箱获取回复消息
由于您还没有绑定你的真实邮箱,如果其他用户或者作者回复了您的评论,将不能在第一时间通知您!
发布评论
评论(3)
自动变量和递归函数调用都会消耗堆栈内存。您两者都大量使用。
您可以用迭代替换递归(从递归到迭代的方法 )并且您可以将自动变量(巨型数组)替换为堆分配的变量(使用
new
)。做这两件事应该会对你有所帮助。只要确保当您对 Collatz 函数采用迭代方法时,您使用的是堆分配的堆栈,这样您就不会再次遇到相同的问题!
Stack memory is consumed by both automatic variables and recursive function calls. You use large amounts of both.
You can replace recursion with iteration (Way to go from recursion to iteration) and you can replace your automatic variable (the giant array) with a heap-allocated one (using
new
).Doing both of these things should help you here. Just make sure when you go to an iterative approach for your Collatz function that you use a heap-allocated stack so you don't get the same problem all over again!
堆栈通常具有固定的、相当小的大小——也许是几兆字节。您正在做的两件事很容易导致过多的堆栈使用:
第一个可以通过使用计数器的动态数组来修复:
或者不存储所有结果,只存储每次迭代后找到的最大结果。
第二个问题可以通过检查编译器是否优化了递归或迭代实现来解决;像这样的东西(未经测试):(
如果您确实决定保留递归实现,那么您需要通过引用传递
currentcounter
,或者使用每个递归调用的返回值更新它并记住此外,main()
中的数组索引应从0
到N-1
,而不是从 <代码>1到N
。main()
必须返回int
,尽管您可以根据需要省略return
语句) 。The stack is typically of a fixed, fairly small size - perhaps a few megabytes. You are doing two things which could easily cause too much stack use:
The first can be fixed by using a dynamic array for the counters:
or by not storing all the results, just the largest you've found after each iteration.
The second can be fixed by either checking that the compiler does optimise out the recursion, or implementing it iteratively; something like this (untested):
(If you do decide to keep your recursive implementation, then you'll need to either pass
currentcounter
by reference, or update it with the return value of each recursive call and remember to return a value in all cases. Also, your array indexes inmain()
should run from0
toN-1
, not from1
toN
. Andmain()
must returnint
, although you can leave out thereturn
statement if you want).在计算如此大的数字的 Collatz 链时,
long int
会溢出。我认为这就是你的递归函数出错的原因。尝试将c1
参数更改为 64 位类型,例如long long
。我刚刚对此进行了测试,当您达到值 704511 时,链范围高达 56991483520。顺便说一句,这是 Project Euler 问题 14。
编辑:
将数组
totalcounter[]
的声明移到main()
函数使其成为全局的。对于堆栈上的自动存储而言,它太大了(~4MB)。其他替代方案是动态分配数组或使用 std::vector 。此处的代码示例。
In computing the Collatz chain for such large numbers you are overflowing a
long int
. I assume that's why your recursive function is faulting. Try changing yourc1
parameter to a 64-bit type such aslong long
.I just tested this and when you reach the value 704511 the chain ranges as high as 56991483520. By the way, this is Project Euler problem 14.
Edit:
Move your declaration of the array
totalcounter[]
outside themain()
function to make it a global. It's simply too large (~4MB) for automatic storage on the stack. Other alternatives would be to dynamically allocate the array or usestd::vector
.Example of your code working here.