无限递归函数->堆栈溢出错误

Posted

技术标签:

【中文标题】无限递归函数->堆栈溢出错误【英文标题】:Infinite recursive function -> Stack Overflow error 【发布时间】:2017-09-05 20:24:43 【问题描述】:

我在java中有一个无限递归循环

public  void infiniteLoop(Long x)

    System.out.println(""+x);
    infiniteLoop(x + 1);


public static void main(String[] args) 

    *** st = new ***();
    st.infiniteLoop(0L); 

在这段代码中,它按预期显示了一个 *** 错误,但如果我查看控制台输出,该错误会显示在多行中:

4806
4807
4808
    at java.io.BufferedWriter.flushBuffer(BufferedWriter.java:129)
    at java.io.PrintStream.write(PrintStream.java:526)
    at java.io.PrintStream.print(PrintStream.java:669)
    at java.io.PrintStream.println(PrintStream.java:806)
    at ***.***.infiniteLoop(***.java:234809
)
    at ***.***.infiniteLoop(***.java:24)
    at ***.***.infiniteLoop(***.java:24)
4810
4811
4812

我的问题是,为什么会发生这种情况?它不应该在显示第一个 Stack Overflow 错误后立即停止吗?

【问题讨论】:

可能会缓冲stdout,并在stderr 到达后立即打印,然后在崩溃后刷新stdout 这是因为错误写入stderr,而输出写入stdout。这些可能不会很好地同步。 【参考方案1】:

[S]不应该在显示第一个 Stack Overflow 错误后立即停止吗?

实际上程序在第一个***异常处停止。但是异常写入stderr 通道(所以System.err.println(..)),而您将输出打印到stdout 通道。

终端监听这两个频道并旨在以一种好的方式打印它们,但由于这些是单独的频道,因此保证显示生产者写入频道的顺序正确:各个通道的顺序总是正确的,但如果数据(几乎)同时写入两个通道,流可能会有点混淆。

您也可以更改程序以打印到stderr

public void infiniteLoop(Long x)
    System.err.println(""+x); // error channel.
    infiniteLoop(x + 1);

现在数据写入通道的顺序也应该是终端显示的顺序。

【讨论】:

以上是关于无限递归函数->堆栈溢出错误的主要内容,如果未能解决你的问题,请参考以下文章

分段错误和堆栈溢出有啥区别?

如何启用递归函数以避免堆栈溢出?

由于堆栈溢出,C 中通常会发生啥?

导致堆栈溢出异常的嵌套 JSF 复合组件

递归 - 堆栈溢出错误

堆栈溢出一般是由啥原因导致的?