【问题标题】:Stack Overflow error in recursive C++ function [duplicate]递归C ++函数中的堆栈溢出错误[重复]
【发布时间】:2013-09-20 18:27:20
【问题描述】:
#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;
}

这个函数在count的值超过4800后溢出堆栈,谁能告诉我如何解决这个问题?

【问题讨论】:

  • 这很明显,但使用更大的堆栈。你如何做到这一点取决于你的编译器/链接器。
  • int f() { ... return f(); },递归是有限的。每个深度级别都需要在堆栈上放一点,而后者并非无底洞。
  • 开启优化?用“return 5000”替换整个函数?或者将你的值初始化为 4999。

标签: c++


【解决方案1】:

不要使用递归 - 使用常规循环。每次调用你的f()方法,你都会在栈上占据几个字,并且在某个时候会溢出。

通常,有办法增加堆栈大小(取决于您的系统和/或编译器),但我不建议这样做(特别是因为它会再次溢出,只是 count 的值大于 4800)。

或者只是 int f(){ return 5000; } 可以。

【讨论】:

    【解决方案2】:

    假设你想递归运行,你可以关闭调试模式,然后你会成功(因为 Visual Studio 在堆栈上添加了额外的东西来检测你是否“破坏”堆栈[这就是它可以说“堆栈围绕变量 x 被覆盖”或任何确切的消息]。

    但是,依靠能够递归地执行大量调用通常是一个糟糕的计划 - 在某些时候,它仍然会失败。无论是 5000、50000 还是 500000 都只是“这个函数占用多少堆栈空间”的问题。我会说任何没有大约 100 级递归的自然限制都是“您以错误的方式解决问题”的情况。如果您确实有如此大的递归级别,最好使用软件堆栈(例如 C++ 中的std::stack),并将当前状态保存在该堆栈上,然后使用函数内部的软件恢复它。

    堆栈空间用完是最糟糕的运行时问题之一,因为您确实无能为力 - 您可能可以做一些事情来打印错误消息或类似的东西,但实际上没有办法“给该过程更多的堆栈空间并继续”。当一个进程内存不足或类似情况时,你可以说“好的,我不会分配它,并给用户一个很好的错误消息说'我不能这样做',然后很好地保存当前状态和例如退出。”

    [是的,您可以增加应用程序的堆栈大小,但这确实应该作为真正的最后手段,并且只有当您完全理解为什么需要如此大的堆栈时 - 通常情况下您需要这样做'如果你需要更大的堆栈,那就错了]。

    【讨论】:

      【解决方案3】:

      我假设这是为了学习递归的学术练习。 (如果不是,请不要为此使用递归!)

      编写函数的更好方法:

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

      与返回常量或循环递增相比,这仍然会消耗更多的运行时资源,如果您将所需的常量增加到更大的数字,则需要增加堆栈大小。

      【讨论】:

      • //我想使用递归。我想要一种增加堆栈大小的方法,请告诉我
      • 这将取决于您的编译器,因为您将不得不告诉编译器增加程序的堆栈。
      猜你喜欢
      • 1970-01-01
      • 2016-11-11
      • 1970-01-01
      • 2017-09-05
      • 2019-08-25
      • 2018-03-10
      • 2014-08-27
      • 2020-09-11
      • 2017-10-20
      相关资源
      最近更新 更多