繁体   English   中英

为什么不总是发生堆栈溢出?

[英]Why doesn't a stack overflow always occur?

我正在学习Java,作为我学习的一部分,我试图故意引起堆栈溢出,看看它会做什么。

我做了一些边界测试,有趣的是,我发现如果我执行以下代码,它只会偶尔导致错误。 有时它会毫无问题地运行。

public class SO
{
    public static void main(String[] args)
    {
        ohno(0);
    }

    public static void ohno(int a)
    {
        System.out.println(a);
        if (a != 11413)
            ohno(a+1);
    }
}

我的问题如下:

  • 什么可能导致我的堆栈大小在这个非常简单的例子的执行之间变化?
  • 现在,由于代码设计不当(即无限递归,过大的基元等),是否总是会发生堆栈溢出,或者是否存在堆栈仍然是技术限制的真实场景?
  • 这个看起来很明显,但是..增加系统的物理内存是否也增加了堆栈的大小?

有限的堆栈大小是您分配给JVM的内存量的函数。

资源受限的系统具有分配较少的内存,所以绝对有现实世界的场景中栈的大小是一个限制,而有些情况下,你必须使用迭代解决方案,以自然递归问题,结果倍。

增加系统的物理内存只对您允许JVM分配内存很重要,否则您将获得该平台的默认值。

发生StackOverflowException的可能性取决于您分配的内存量,使用参数XmxM / G表示最大内存,XmxS / G表示最少。

堆栈溢出可能发生在任何情况下,如果存在死循环,或者有可能通过自动循环获得大量数据(这会消耗大量内存)的数据。

许多编译器检测尾递归调用并为该调用重用相同的堆栈帧,从而防止此类调用增加堆栈。 尾递归调用是递归调用是方法或函数中的最后一条指令的调用。 此优化允许您使用尾递归而不必担心堆栈溢出。

如果引发溢出,请尝试在递归调用后添加一些代码以防止优化。 您可能需要稍微玩一下 - 好的编译器很狡猾,可能会破坏简单的尝试。

暂无
暂无

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

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