用 C# 编写的递归解释器中的 StackOverflowException

分享于2022年07月17日 c# recursion stack-overflow 问答
【问题标题】:用 C# 编写的递归解释器中的 StackOverflowException(StackOverflowException in recursive interpreter written in C#)
【发布时间】:2022-07-14 20:24:21
【问题描述】:

我正在尝试用 C# 创建一个简单的解释器。 我的想法是使用递归。 所以我有这个功能:

void InterpretLine(int lineIndex, string[] lines)
{
    // Do interpreter stuff

    InterpretLine(lineIndex + 1, lines);
}

如您所见,这使用了递归。我使用递归来做到这一点,因为这样我就不必处理函数堆栈和其他东西了。 这适用于少于 100 行的输入代码,但如果它达到太多行,则会抛出 System.StackOverflowException

有没有比递归更好的方法?

  • 你不应该对这个问题使用递归。查看 converting recursive algorithms to loops
  • 具体是哪里抛出的异常?堆栈跟踪会很有用。
  • @JohnGlenn 堆栈跟踪将是 430 次调用深度大声笑
  • 嘿嘿...是的,但是必须复制整个内容可能是一种启发性的体验。这是一个卑鄙的问题吗? :)
  • 这些方法的代码太多了。还有太多的代码重复。拆分成更小的方法,并创建更多的方法来消除代码重复。

【解决方案1】:

您将不得不更改您的逻辑以不使用递归来读取每一行。如果您使用递归,您将为每一层递归添加一个新的函数调用到堆栈中,并且在满足退出条件之前不会删除先前的函数调用。如果将其设置为 500 次左右的深度调用,则可能会出现 stackoverflow 异常。

现在,我没有时间阅读您的代码,但我可以告诉您需要做什么:将递归调用变成循环。

你的代码大概可以分解成这样的:

void ExecuteProgramLine(int lineNumber)
{
   InterpretAndRunLine(lineNumber);
   ExecuteProgramLine(lineNumber + 1);
}

您需要将其转换为:

for(int lineNumber = 0; lineNumber < fileLines) // (foreach loop is probably better)
{
    InterpretAndRunLine(lineNumber);
}