【问题标题】:Process is terminated due to StackOverflowExeption - C#进程因 StackOverflowExeption 而终止 - C#
【发布时间】:2016-05-11 18:47:00
【问题描述】:

我的代码有这个问题,我无法修复。

我正在做一个测验,但这些问题不能被问两次,所以我避免了这种情况,但是当它用完选项时它会崩溃。

也可能是后面的代码,但我不这么认为。

这是我的代码:

private static void chooseQuestion()
{
    Random randomQuestion = new Random();

    int returnValue = randomQuestion.Next(1, 3);

    switch (returnValue)
    {
        case 1:
            if (randomValues.questionOneChosen != 1)
            {
                questionOne();
            }else
            {
                chooseQuestion();
            }
            break;
        case 2:
            if (randomValues.questionTwoChosen != 1)
            {
                questionTwo();
            }else
            {
                chooseQuestion();
            }
            break;
    }

    endQuiz();
}

这是它之后的内容:

private static void endQuiz()
{
    Console.Clear();
    Console.WriteLine();
    text.centered("You completed the QUIZ, well done!");
    Console.WriteLine();
    text.centeredWrite("Press ENTER to go back to the menu");
    string input = Console.ReadLine();
    if (input == "")
    {
        Menu.main();
    }else
    {
        endQuiz();
    }
}

如果您需要更多代码来帮助我,请询问我。

提前致谢!

【问题讨论】:

  • 每次从 endQuiz 读取一行时,您再次调用 endQuiz,这将最终导致 StackOverflow,您还从 StackOverflow 的另一个来源chooseQuestion 调用 chooseQuestion。您必须重新设计所有逻辑,为您的代码获取一个主循环,然后从那里调用返回结果的函数,这样您就不会出现堆栈溢出。
  • 我认为问题出在 endQuiz() 中。你想在那里做什么?您正在从控制台读取一行,然后如果它不是空行,那么您将重新调用 endQuiz()?
  • 你应该重新考虑你的设计。如果您想添加更多问题怎么办?
  • endQuiz 永远无法到达...

标签: c# crash stack-overflow


【解决方案1】:

StackOverflow 上的 StackOverflowException,很好! Menu.main() 最终会调用chooseQuestion() 吗? 调用函数时,会在堆栈上创建一个新条目,其中包含所有局部变量的空间以及返回时要返回的地址。如果一个函数调用自己(递归调用),它的原始堆栈条目不会被释放。如果它经常调用自己而不返回,堆栈最终会用完空间并给出这个异常。话虽如此,堆栈非常大 - 我认为默认值为 1 兆字节 - 所以你需要大量的递归调用来耗尽它。

你有两个函数都调用自己。如果他们经常这样做,您将耗尽堆栈空间。只需用循环替换递归调用。这是您的第一个函数:

private static void chooseQuestion() 
{    
    bool endQuizChosen = false;
    while ( !endQuizChosen ) {
        Random randomQuestion = new Random();
        int returnValue = randomQuestion.Next(1, 3);  
        // ... the rest of the function ...
        endQuizChosen = endQuiz();
    }
}

并编辑endQuiz() 使其不调用自身,但如果用户想停止则返回true,如果用户想继续则返回false

【讨论】:

  • 非常感谢您的解决方案!
【解决方案2】:

您的chooseQuestion 方法的逻辑如下:

a. Pick a 1 or 2, randomly
b. If 1, and I haven't asked question 1 yet, show question 1
c. if 1, and I have asked question 1, go to step (a)
d. repeat (b) and (c) for question 2
...

一旦你回答了这两个问题,你就会尝试得到另一个随机问题。但是没有更多可用的问题。所以你递归到一个异常中。

不要这样写你的逻辑。使用集合,并在您显示该问题后从集合中删除该项目。当集合为空时,您就完成了。

【讨论】:

  • 但是当开关没有选择任何东西时,它只会转到下一行,对吗?那里告诉它去下一段代码
  • 不,您的切换将落入else 语句,并再次调用您的方法。你永远不会到达endQuiz()。您可以(并且应该)调试代码并观察它自己运行
  • 哦,我明白了,非常感谢,但是你知道我的代码怎么写吗?我只是 C# 的新手,所以我不知道如何解决它...
  • 你应该从重新思考你的逻辑开始,然后着手 C# 实现
  • 确定。在此站点上,如果您找到对您有帮助的答案,请单击绿色复选框接受该答案。确定逻辑后,您可以返回有关您的实现的特定 C# 问题。
【解决方案3】:

这永远不会设置。

randomValues.questionOneChosen

所以无论它是什么,如果它不是 1 或 2,则该方法将再次调用自身。它可能总是为零。

【讨论】:

  • 不,那是另一段代码:class randomValues { public static int questionOneChosen; public static int questionTwoChosen; }
猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 2020-11-02
  • 1970-01-01
  • 1970-01-01
  • 2019-01-04
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多