#include<iostream>
using namespace std;
int f()
{
static int count=0;
count++;
if (count>=5000)
return count;
return f();
}
int main ()
{
cout<<f();
return 0;
}
此函数在计数值超过 4800 后溢出堆栈有人能告诉如何解决这个问题吗?
#include<iostream>
using namespace std;
int f()
{
static int count=0;
count++;
if (count>=5000)
return count;
return f();
}
int main ()
{
cout<<f();
return 0;
}
此函数在计数值超过 4800 后溢出堆栈有人能告诉如何解决这个问题吗?
不要使用递归 - 使用常规循环。每次你调用你的f()
方法时,你会在栈上占据几个字,并且在某个时候你会溢出它。
通常,有办法增加堆栈大小(取决于您的系统和/或编译器),但我不建议这样做(特别是因为它会再次溢出,只是 count 的值大于 4800)。
或者只是int f(){ return 5000; }
会做。
假设你想递归运行,你可以关闭调试模式,然后你会成功(因为 Visual Studio 在堆栈上添加了额外的东西来检测你是否“破坏”堆栈[这就是它可以说“变量周围的堆栈x
是覆盖”或任何确切的消息]。
然而,依靠能够递归地进行大量调用通常是一个糟糕的计划 - 在某些时候,它仍然会失败。无论是 5000、50000 还是 500000 都只是“这个函数占用多少堆栈空间”的问题。我会说任何没有大约 100 级递归的自然限制都是“你以错误的方式解决问题”的情况。如果您确实有如此大的递归级别,最好使用软件堆栈(例如std::stack
在 C++ 中),并将当前状态保存在该堆栈上,然后使用函数内部的软件恢复它。
堆栈空间用完是最糟糕的运行时问题之一,因为您确实无能为力 - 您可能可以做一些事情来打印错误消息或类似的东西,但实际上没有办法“给进程一些更多堆栈空间并继续”。当进程内存不足或类似情况时,您可以说“好的,我不会分配它,并给用户一个很好的错误消息说'我不能这样做',然后很好地保存当前状态和例如,退出。”
[是的,您可以增加应用程序的堆栈大小,但这确实应该作为真正的最后手段,并且只有当您完全理解为什么需要如此大的堆栈时——这通常是您正在做的其他事情如果你需要更大的堆栈,那就错了]。
我假设这是为了学习递归的学术练习。(如果不是,请不要为此使用递归!)
编写函数的更好方法:
#include <iostream>
int f(int i)
{
if (i >= 5000)
{
return i;
}
else
{
return f(i + 1);
}
}
int f_alt1()
{
return 5000;
}
int f_alt2()
{
int i = 0;
for (; i <= 5000; ++i);
return i;
}
int main()
{
std::cout << f(0) << std::endl;
return 0;
}
与返回常量或循环递增相比,这仍然会消耗更多的运行时资源,并且如果将所需的常量增加到更大的数字,则需要增加堆栈大小。