繁体   English   中英

并行递归期间的 StackOverflowError [Java]

[英]StackOverflowError During Parallel Recursion [Java]

我正在使用并行递归来评估一个数字是奇数还是偶数。 我使用了 long 类型,但是当输入 number(x) 有 5 位或更多位时,我遇到了 StackOverflowError。 我不明白为什么。


    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");
        }
        
        }
        
    }

要了解为什么会出现 StackOverflowError,您需要了解在代码中调用 function 时会发生什么,以及在实际处理器中是如何执行的。

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

但是,当要执行的行是 function 时,function 的代码不会立即在下一个 memory 地址上可用。 相反,这个 function 将在 memory 的不同位置提供。 因此,当处理单元看到 function 调用时,它会复制几个重要的统计数据,例如程序计数器 [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);
  }
}

如您所知,在此示例中,代码执行从 ```main```` function 开始。 所以执行主function的第1行并将attr变量设置为10。然后转到第2行,在这里,它看到有一个function调用即func2。

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

在 func1 中,我们没有 function 调用,因此不再发生堆栈推送。 Func1 有 3 行代码,它们一个接一个地执行。 然而,仅仅因为我们到达了 func1 的末尾,并不意味着我们已经完成了代码的执行。 我们还是要执行func2和main的rest。 我们需要执行的第一组代码是 func2,因为 func2 调用了 func1。 这正是我们在堆栈中的内容(堆栈顶部具有 func2 值)。 所以我们弹出它,继续执行 func2,一旦完成,我们 go 回到堆栈,看到有一个来自主 function 的条目。 所以我们弹出它并完成执行。

现在我们有了一些了解,在您的代码中,您会看到 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-> 
)

所以在这种情况下,对于像 5 这样的小数字,我们看到堆栈的大小高达 6。现在对于像 99999 这样的 5 位数字,堆栈的最大大小将是 100000,这是一个非常大的数字为堆栈。 请记住,对于每个堆栈条目,我们将在堆栈上复制 PC、寄存器等。

这就是为什么您会看到 5 位数字的 StackOverflowError。 当位数为 5 时,堆栈的大小变得非常高,这可能超出了运行代码的处理器的能力。

暂无
暂无

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM