当前位置: 首页 > 知识库问答 >
问题:

并行递归过程中的StackOverflowError[Java]

澹台文博
2023-03-14

    static boolean Odd(long n) {
    if (n == 0) return false;
    else return Even(n - 1);     
    }
    
    static boolean Even(long d) {
    if (d == 0) return true;
    else return Odd(d - 1);  
    }
    
    public static void main(String[] args) {
        long x = 0; 
        while(x>=0) {
            System.out.println("Insert number");
            x = SavitchIn.readLong();
            boolean isOdd = Odd(x);
            if(isOdd) {
                System.out.println("Odd number");
            }else {
                System.out.println("Even number");
        }
        
        }
        
    }

共有1个答案

梁宪
2023-03-14

要理解为什么会得到StackOverflowError,您需要理解在代码中进行函数调用时会发生什么,以及如何在实际处理器中执行。

运行程序时,所有相关联的代码和符号都会加载到内存中,然后逐行执行。您有一个名为Program Counter的寄存器,它基本上充当指向当前执行的代码行的指针。

但是,当要执行的行是一个函数时,该函数的代码不能立即在下一个内存地址上可用。相反,该函数将在内存中的不同位置可用。因此,当处理单元看到一个函数调用时,它复制几个重要的统计数据,如程序计数器[PC](以知道代码执行了多远)、寄存器值等,并将这些数据推入堆栈。此数据结构是堆栈的原因可以通过下面的简单代码示例来解释:

public class Example {
  public int func1() {
    int a = 10, b = 20;
    int c = a+b;
    return c;
  }
  
  public int func2() {
    int a = 100;
    int b = func1();
    return a*b;
  }

  public static void main(String args[]) {
    int attr = 10;
    int result = func2() / 10;
    System.out.println(result);
  }
}

所以此时,系统会将PC机和其他内存推入堆栈,然后移动到FUNC2的位置。在func2中,执行第1行时将a的值设置为100。func2的第2行再次是一个函数调用,因此,所有的数据现在再次被推送到堆栈上,并执行func1。

在func1中,我们没有函数调用,因此不再发生堆栈推送。Func1有3行代码,它们一个接一个地执行。但是,仅仅因为我们到达了func1的末尾,并不意味着我们已经完成了代码的执行。我们仍然必须执行func2和main的其余部分。我们需要执行的第一组代码是func2,因为func2名为func1。这正是我们在堆栈中所拥有的(堆栈顶部有func2值)。因此,我们弹出它,继续执行func2,一旦完成,我们回到堆栈,看到有一个来自main函数的条目。所以我们把它弹出来,完成执行。

现在我们已经了解了这一点,在您的代码中,您可以看到,Odd()和Even()方法递归地相互调用。对于少量的5,我们看到以下情况:

Main( 
  -push-> Odd(5 
    -push-> Even(4 
      -push-> Odd(3 
        -push-> Even(2 
          -push-> Odd(1 
            -push-> Even(0 
              [return's true]
            ) -pop-> 
          ) -pop->
        ) -pop->
      ) -pop-> 
    ) -pop-> 
  ) -pop-> 
)
 类似资料:
  • 问题内容: 我正在编写一个函数,该函数最多可以调用5000次。当然,我得到了。有什么办法可以以一种非常简单的方式重写此代码?: 顺便说一下,我们可以调用这些函数的深度有什么限制? 问题答案: 使用显式的对象堆栈和循环,而不是调用堆栈和递归:

  • 问题内容: 问题的背景:我正在尝试编写一个难题解决方案算法,该算法利用多核处理器和并行处理的优势。但是,理想/最简单的解决方案是简单的递归函数。 分解解决方案以同时利用并行处理 和 递归函数的最佳方法是什么? 下面的代码是一种简单的难题解决算法的解决方案(它可以正常工作)。这个例子中的难题很简单-有14个插槽,编号为1-14。每个拼图都有一个唯一的ID,一个告诉您可以在哪里开始和停止的范围(例如6

  • 是否可以在HSQLDB中创建递归存储过程? 我编写了以下一个来更新一个记录,并递归地更新所有父记录: 但我得到了以下错误: 在HyperSQL用户指南中,我找到了一些信息(请参阅HyperSQL用户指南中的递归例程),但它似乎只支持函数。 提前感谢您的支持。

  • 最后一个函数返回15->20,然后组合为root.next->temp,但是在返回temp的步骤之后,为什么会返回根值。即10->15->20,而我希望只返回temp。 请找到代码,

  • 我正在尝试编写一个ruby方法,它可以递归地执行合并排序。我有这个方法,但这是一次我偶然得到它的工作,所以我不知道它为什么工作,并很想了解我写的代码是如何工作的。在psuedocode中,我遵循的步骤如下所示。 拆分长度为n的原始数组,直到我拥有长度为1的n个数组 一次合并和排序长度为m的2个数组,以返回长度为m*2的数组 重复上述步骤,直到我有一个长度为n的当前排序数组 基本上,在我看来,这是一

  • 我需要编写一个递归方法,它需要两个并行数组和单词来查找,查找指定的单词并在另一个数组上每次索引匹配时求和值。例如: 如果我说我需要查找单词,它应该在找到索引时对第二个数组上的值求和。在这种情况下,它应该求和,。 如何使我的递归方法使其采用适当的参数并递归地进行计算。我将使用硬编码值。 这是我目前所拥有的。我很确定我的递归方法需要更多参数,但我会看看是否有人能帮助我