堆栈溢出错误 java

声明:本页面是StackOverFlow热门问题的中英对照翻译,遵循CC BY-SA 4.0协议,如果您需要使用它,必须同样遵循CC BY-SA许可,注明原文地址和作者信息,同时你必须将它归于原作者(不是我):StackOverFlow 原文地址: http://stackoverflow.com/questions/6272362/
Warning: these are provided under cc-by-sa 4.0 license. You are free to use/share it, But you must attribute it to the original authors (not me): StackOverFlow

提示:将鼠标放在中文语句上可以显示对应的英文。显示中英文
时间:2020-10-30 15:08:23  来源:igfitidea点击:

Stack Overflow Error java

javarecursionstack-overflowbacktracking

提问by user658168

I'm trying to solve a problem that calls for recursive backtracking and my solution produces a stackoverflow error. I understand that this error often indicates a bad termination condition, but my ternimation condition appears correct. Is there anything other than a bad termination condition that would be likely to cause a stackoverflow error? How can I figure out what the problem is?

我正在尝试解决一个需要递归回溯的问题,而我的解决方案产生了一个堆栈溢出错误。我知道此错误通常表示终止条件不好,但我的终止条件似乎正确。除了可能导致计算器溢出错误的不良终止条件之外,还有什么其他原因吗?我怎样才能找出问题所在?

EDIT: sorry tried to post the code but its too ugly..

编辑:抱歉试图发布代码,但它太丑了..

回答by Aasmund Eldhuset

As @irreputable says, even if your code has a correct termination condition, it could be that the problem is simply too big for the stack (so that the stack is exhausted before the condition is reached). There is also a third possibility: that your recursion has entered into a loop. For example, in a depth-first search through a graph, if you forget to mark nodes as visited, you'll end up going in circles, revisiting nodes that you have already seen.

正如@irreputable 所说,即使您的代码具有正确的终止条件,也可能是问题对于堆栈来说太大了(因此在达到条件之前堆栈已耗尽)。还有第三种可能性:你的递归进入了一个循环。例如,在通过图形进行深度优先搜索时,如果您忘记将节点标记为已访问,您最终会绕圈子,重新访问您已经看过的节点。

How can you determine which of these three situations you are in? Try to make a way to describe the "location" of each recursive call (this will typically involve the function parameters). For instance, if you are writing a graph algorithm where a function calls itself on neighbouring nodes, then the node name or node index is a good description of where the recursive function is. In the top of the recursive function, you can print the description, and then you'll see what the function does, and perhaps you can tell whether it does the right thing or not, or whether it goes in circles. You can also store the descriptions in a HashMap in order to detect whether you have entered a circle.

您如何确定您处于这三种情况中的哪一种?尝试设法描述每个递归调用的“位置”(这通常涉及函数参数)。例如,如果您正在编写一个函数在相邻节点上调用自身的图算法,那么节点名称或节点索引是递归函数所在位置的一个很好的描述。在递归函数的顶部,你可以打印描述,然后你会看到函数做了什么,也许你可以判断它是否做对了,或者它是否在循环。您还可以将描述存储在 HashMap 中,以检测您是否进入了一个圆圈。

回答by David Weiser

Instead of using recursion, you could always have a loop which uses a stack. E.g. instead of (pseudo-code):

除了使用递归,你总是可以有一个使用堆栈的循环。例如,而不是(伪代码):

function sum(n){
  if n == 0, return 0
  return n + sum(n-1)
}

Use:

利用:

function sum(n){
  Stack stack
  while(n > 0){
    stack.push(n)
    n--
  }
  localSum = 0
  while(stack not empty){
    localSum += stack.pop()
  }
  return localSum
}

In a nutshell, simulate recursion by saving the state in a local stack.

简而言之,通过将状态保存在本地堆栈中来模拟递归。

回答by Ashkan Paya

As the other fellas already mentioned, there might be few reasons for that:

正如其他人已经提到的,可能有几个原因:

  • Your code has problem by nature or in the logic of the recursion. It has to be a stoping condition, base case or termination point for any recursive function.
  • Your memory is too small to keep the number of recursive calls into the stack. Big Fibonacci numbers might be good example here. Just FYI Fibonacci is as follows (sometimes starts at zero):

    1,1,2,3,5,8,13,...

    Fn = Fn-1 + Fn-2

    F0 = 1, F1 = 1, n>=2

  • 您的代码本质上或递归逻辑存在问题。它必须是任何递归函数的停止条件、基本情况或终止点。
  • 您的内存太小,无法将递归调用的数量保留到堆栈中。大斐波那契数列在这里可能是一个很好的例子。仅供参考 Fibonacci 如下(有时从零开始):

    1,1,2,3,5,8,13,...

    Fn = Fn-1 + Fn-2

    F0 = 1, F1 = 1, n>=2

回答by JustinKSU

You can use the -Xss option to give your stack more memory if your problem is too large to fix in the default stack limit size.

如果您的问题太大而无法在默认堆栈限制大小中修复,您可以使用 -Xss 选项为您的堆栈提供更多内存。

回答by irreputable

If your code is correct, then the stack is simply too small for your problem. We don't have real Turing machines.

如果您的代码是正确的,那么堆栈对于您的问题来说太小了。我们没有真正的图灵机。

回答by trutheality

There are twocommon coding errors that could cause your program to get into an infinite loop (and therefore cause a stack overflow):

两种常见的编码错误可能会导致您的程序进入无限循环(从而导致堆栈溢出):

  • Bad termination condition
  • Bad recursion call
  • 糟糕的终止条件
  • 错误的递归调用

Example:

例子:

public static int factorial( int n ){
    if( n < n ) // Bad termination condition
        return 1;
    else
        return n*factorial(n+1); // Bad recursion call
}

Otherwise, your program could just be functioning properly and the stack is too small.

否则,您的程序可能只是正常运行而堆栈太小。