垃圾收集器如何在这里避免无限循环?
本文关键字:无限循环 在这里 收集器 | 更新日期: 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秒后程序终止(换句话说,垃圾收集器放弃,只是释放所有内存而不考虑终结器)。