垃圾收集器在这里如何避免无限循环?
考虑下面的C#程序,我在codegolf上提交它作为创build一个没有循环的循环的答案:
class P{ static int x=0; ~P(){ System.Console.WriteLine(++x); new P(); } static void Main(){ new P(); } }
这个程序在我的检查中看起来像一个无限循环,但似乎运行了几千次迭代,然后程序成功终止,没有错误(没有错误抛出)。 这是一个规范侵犯,最终的P
终结者不被称为?
显然这是愚蠢的代码,应该永远不会出现,但我很好奇程序如何完成。
原码高尔夫球杆:: https://codegolf.stackexchange.com/questions/33196/loop-without-looping/33218#33218
根据CLR第二版中的Richter,通过C#(是的,我需要更新):
页面478
对于(CLR正在closures),每个Finalize方法都会返回大约两秒。 如果Finalize方法在两秒内没有返回,那么CLR只会杀死进程 – 不会再调用Finalize方法。 而且,如果再花费40秒钟时间来调用所有对象的Finalize方法,那么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
并杀死程序。 五秒钟后程序终止(换句话说,垃圾收集器放弃,只是将所有内存释放,而不考虑终结器)。