3

我是编程新手,我正在尝试自学 StackOverflow 是由什么引起的。我玩弄循环并导致错误,但我测试的 forkbomb 代码不会导致错误。为什么是这样?

public class ForkBomb
{
  public static void main(String[] args) throws java.io.IOException 
  {
     while(true) 
    {
        Runtime.getRuntime().exec(new String[]{"java", "-cp", System.getProperty("java.class.path"), "ForkBomb"});
    }
  }
}

这不会导致堆栈溢出。为什么?然而,这导致了一个:

public class WhileBomb
{
   public WhileBomb()
   {
      while (true)
      {
      new WhileBomb();
      }
   }

   public static void main(String[] args) throws java.io.IOException
   {
     WhileBomb goodBye = new WhileBomb();
   }
}
4

3 回答 3

11

每个线程都有自己的堆栈。当您创建一个新进程时,您还将获得一个新线程和一个新堆栈。当一个堆栈被填满时会发生堆栈溢出错误,但您正在创建许多不同的堆栈,但没有一个堆栈被填满。

在第二个示例中,您只有一个线程并且您有一个递归调用。每次调用方法时,一些信息都会临时存储在堆栈中,直到方法返回。因为你的方法永远不会返回堆栈,直到你得到堆栈溢出异常。

你甚至不需要 while 循环。这也会产生堆栈溢出异常:

public WhileBomb()
{
   new WhileBomb();
}
于 2013-01-15T14:23:16.140 回答
2

第一个示例没有向堆栈添加任何内容,而是创建了全新的堆栈。但是,第二个示例在此处添加到堆栈中:

public WhileBomb()
{
    while (true)
    {
        new WhileBomb();
    }
}

你在这里看到的是一个无限递归。创建WhileBomb对象涉及创建WhileBomb对象。这一切都发生在同一个程序的同一个线程中(不是分叉一个新线程),所以它在同一个堆栈中。线程中每次创建新WhileBomb的都会将自身的另一个实例添加到堆栈中。

于 2013-01-15T14:24:10.753 回答
1

堆栈溢出是由于使用的堆栈空间多于可用空间造成的。叉子炸弹通过产生大量新进程来减慢 PC 的速度,每个新进程都会不断产生更多(等等)。

fork 炸弹不会导致堆栈溢出的原因是每个进程都有自己的堆栈,因此您实际上并没有在任何进程中使用太多堆栈空间,只是创建了许多进程,每个进程都有自己的(相对较小的)堆栈。

于 2013-01-15T14:23:54.363 回答