垃圾收集器如何在这里避免无限循环?

本文关键字:无限循环 在这里 收集器 | 更新日期: 2023-09-27 18:12:08

考虑以下c#程序,我在codegolf上提交了它,作为创建一个不循环的循环的答案:

class P{
    static int x=0;
    ~P(){
        System.Console.WriteLine(++x);
        new P();
    }
    static void Main(){
        new P();
    }
}

在我的检查中,这个程序看起来像一个无限循环,但它似乎运行了几千次迭代,然后程序成功终止,没有错误(没有抛出错误)。P的终结器最终不被调用是否违反了规范?

显然这是愚蠢的代码,不应该出现,但我很好奇这个程序是如何完成的。

原始代码高尔夫帖子::33218年https://codegolf.stackexchange.com/questions/33196/loop-without-looping/33218

垃圾收集器如何在这里避免无限循环?

根据Richter通过c#发布的CLR第二版(是的,我需要更新):

478页

对于(CLR正在关闭),每个Finalize方法大约有两秒钟的返回时间。如果Finalize方法没有在两秒钟内返回,CLR就会终止该进程——不再调用Finalize方法。同样,如果调用所有对象的Finalize方法的时间超过40秒,CLR将再次终止该进程。

而且,正如Servy提到的,它有自己的线程

终结器不在主线程中运行。终结器有自己的线程来运行代码,它不是一个前台线程来保持应用程序的运行。主线程立即有效地完成,此时终结器线程只是在进程被关闭之前尽可能多地运行几次。

垃圾收集器不是活动系统。它"有时"运行,并且主要是按需运行(例如,当操作系统提供的所有页面都已满时)。

大多数垃圾收集器在子线程中以类似于宽度优先代的方式运行。在大多数情况下,回收物品可能需要几个小时。

唯一的问题发生在你想终止程序的时候。然而,这并不是真正的问题。当您使用kill时,操作系统将礼貌地要求终止进程。但是,当进程保持活动状态时,可以使用kill -9,操作系统将删除所有控制。

当我在交互式csharp环境中运行您的代码时,我得到:

csharp>  
1
2
Unhandled Exception:
System.NotSupportedException: Stream does not support writing
  at System.IO.FileStream.Write (System.Byte[] array, Int32 offset, Int32 count) [0x00000] in <filename unknown>:0 
  at System.IO.StreamWriter.FlushBytes () [0x00000] in <filename unknown>:0 
  at System.IO.StreamWriter.FlushCore () [0x00000] in <filename unknown>:0 
  at System.IO.StreamWriter.Write (System.Char[] buffer, Int32 index, Int32 count) [0x00000] in <filename unknown>:0 
  at System.IO.CStreamWriter.Write (System.Char[] buffer, Int32 index, Int32 count) [0x00000] in <filename unknown>:0 
  at System.IO.CStreamWriter.Write (System.Char[] val) [0x00000] in <filename unknown>:0 
  at System.IO.CStreamWriter.Write (System.String val) [0x00000] in <filename unknown>:0 
  at System.IO.TextWriter.Write (Int32 value) [0x00000] in <filename unknown>:0 
  at System.IO.TextWriter.WriteLine (Int32 value) [0x00000] in <filename unknown>:0 
  at System.IO.SynchronizedWriter.WriteLine (Int32 value) [0x00000] in <filename unknown>:0 
  at System.Console.WriteLine (Int32 value) [0x00000] in <filename unknown>:0 
  at P.Finalize () [0x00000] in <filename unknown>:0

因此您的程序崩溃,因为stdout被环境终止阻塞。

当删除Console.WriteLine并杀死程序时。如果在5秒后程序终止(换句话说,垃圾收集器放弃,只是释放所有内存而不考虑终结器)。