【问题标题】:How can I handle System.StackOverflowException?如何处理 System.StackOverflowException?
【发布时间】:2016-01-12 00:36:35
【问题描述】:

此错误有时仅在我调用其中一个参数是数字的递归函数时出现:rand()%10。就像下面的代码一样:

private: System::Void AIrandomMove(int randomMove,String ^s)
{
if (randomMove == 1)
{
    if ( Move(1) ) // move number 1 had already been done
        AIrandomMove(rand()%10,s);  // here it appears the    System.StackOverflowException
    else
         //do move number 1
}
//same goes for ==2 || ==3 || ... || ==10
}

我该如何处理?

【问题讨论】:

  • 只是不要依赖递归代码,因为它没有任何意义。将算法转换为迭代算法。
  • 为什么没有意义?实现如下: else //实现 }`
  • 这没有意义,因为您明确允许非终止行为。使用递归有什么意义?我的意思是你为什么需要递归?
  • @RazvanNica 请edit您的帖子包含所有相关细节,并避免将这些细节放在 cmets 中。
  • 那是因为递归算法的终止取决于随机值提取,正如我在第一条评论中指出的那样,所以你基本上有一些代码可能会或可能不会根据你的幸运程度而终止,这不是一个合适的设计。

标签: random stack c++-cli overflow system


【解决方案1】:

一个合适的递归算法在两个假设下工作:

  • 你有一个终止递归的基本情况(所以函数不会调用自己)
  • 您有一个递归案例,它使用不同的参数调用函数本身,因此涉及一些进展

这翻译成这样的:

void recursive(inArgs) {
  if (condition)
    return;
  else
    recursive(outArgs)
}

很明显,如果condition 是表达式true,那么这段代码永远不会终止(因此它最终会引发堆栈溢出)。

在您的情况下,condition 是通过随机值比较进行评估的。现在,假设条件是rand()%2 == 0。所以基本上每次评估时,您都有50% 成为true50% 成为false 的机会。

这并不能保证递归将终止,因为存在 n true 评估的路径(并且可以计算它的概率)。这就是你设计的问题。

如果已经进行了许多移动(或者可能全部移动),则递归不会结束。

在您的情况下,您根本不需要递归,因为您可以将可用的移动存储在一个集合中,并在它们不再可用时将其删除(可能将集合打乱,然后随机选择一个)。甚至更简单的解决方案是这样的:

int choosenMove = rand()%10;

while (Move(choosenMove)) {
  choosenMove = rand()%10;
  // do move choosenMove
}

但是,如果您不能确保不会发生没有可用动作的状态,这也不能保证终止。

【讨论】:

  • 哦..好的。现在我终于明白了。非常感谢。我的国家现在是凌晨 3 点,我肯定需要休息一下。尽管如此,我明白了!再次感谢! =)
猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2014-08-03
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2016-05-14
相关资源
最近更新 更多