***Error - 堆栈大小和递归

Posted

技术标签:

【中文标题】***Error - 堆栈大小和递归【英文标题】:***Error - Stack Size & Recursion 【发布时间】:2021-12-15 15:29:17 【问题描述】:

我认为我关于 Stack Overflow 的第一个问题应该是关于堆栈溢出错误......

我使用递归算法解决了 Code Wars 中的“观察到的 PIN”问题:

https://www.codewars.com/kata/5263c6999e0f40dee200059d

import java.util.List;
import java.util.ArrayList;

public class ObservedPin 
  
  static StringBuilder sb = new StringBuilder();
  static int[] digits;
  static int[] index;
  static List<String> perms = new ArrayList<String>();
  static int[][] nums = 0, 8, 1, 2, 4, 1, 2, 3, 5, 2, 3, 6,
    1, 4, 5, 7, 2, 4, 5, 6, 8, 3, 5, 6, 9, 4, 7, 8,
    5, 7, 8, 9, 0, 6, 8, 9;
    
    public static List<String> getPINs(String observed) 
      digits = new int[observed.length()];
      index = new int[observed.length()];
      for (int i = 0; i < digits.length; i++) 
        digits[i] = observed.charAt(i) - 48;
       
      permutations(0);
      return perms;
    
    public static void permutations(int level) 
      if (index[level] == nums[digits[level]].length) 
        if (level == 0) 
          return;
         else 
          index[level] = 0;
          index[level - 1]++;
          level = 0;
           
       else 
        if (level == digits.length - 1) 
          //addPinToList(); **** commented out to see if this affected the required memory ****
          index[level]++;
         else 
          level++;
         
      
      permutations(level);  
    
    public static void addPinToList() 
      for (int i = 0; i < digits.length; i++) 
        sb.append(Integer.toString(nums[digits[i]][index[i]])); 
      
      perms.add(sb.toString());
      sb.setLength(0);
    

在看到其他“最佳实践”和“聪明”的解决方案后,我意识到这绝对不是要走的路,我应该以不同的方式解决问题。无论如何,在测试我的解决方案时,我将一个具有最高可能排列数的 PIN 号传递给了 getPINs 方法。任何完全由 5 和 8 组成的 PIN 将产生 320,625 种可能的排列。我使用了 PIN 58585858。 当我运行代码时,我得到了 ***Error。我对代码进行了一些我认为可能会有所帮助的更改,但没有任何效果。最终我增加了堆栈大小并且代码运行良好。只是出于兴趣,我注释掉了将排列添加到“perms”列表的行,认为这也会减少所需的内存,但是当使用默认的 1Mb 堆栈大小时,我得到了同样的错误。 如果递归方法不创建任何参数或对象,或者对任何现有参数/对象的大小有任何影响,为什么它会占用这么多内存? JVM 是否为每次递归创建一个新的堆栈帧,所以是这些帧占用了内存?

我正在自学,我对此很陌生,您可能已经猜到了。

【问题讨论】:

【参考方案1】:

JVM 是否为每个递归创建一个新的堆栈帧,所以它是 占用内存的帧?

是的。堆栈帧是您需要能够建立执行上下文(也称为“激活记录”)并返回的内容。它至少包含一个返回地址。一般来说,它可能还包含保存的寄存器和例程参数。

Link - stack frame description for JVM

【讨论】:

很高兴知道。感谢那。以后我可能会更加谨慎地使用递归!

以上是关于***Error - 堆栈大小和递归的主要内容,如果未能解决你的问题,请参考以下文章

在 python 2.7 中增加递归限制和堆栈大小

Python递归限制与堆栈大小?

为啥这个递归函数超过调用堆栈大小?

为啥 malloc() 和普通数组声明分配的堆栈帧大小不同?

增加主程序的堆栈大小或为递归代码块创建一个具有更大堆栈大小的新线程?

超出最大调用堆栈大小 - 没有明显的递归