Как сборщик мусора избегает бесконечного цикла здесь?
Рассмотрим следующую программу на С#, я отправил ее на codegolf в качестве ответа на создание цикла без цикла:
class P{
static int x=0;
~P(){
System.Console.WriteLine(++x);
new P();
}
static void Main(){
new P();
}
}
Эта программа выглядит как бесконечный цикл в моей проверке, но, похоже, она запускается в течение нескольких тысяч итераций, а затем программа успешно завершается без ошибок (ошибок не выбрасывается). Является ли это нарушением спецификации, что финализатор для P
в конечном итоге не называется?
Ясно, что это глупый код, который никогда не должен появляться, но мне любопытно, как программа могла бы завершиться.
Оригинальный код для гольфа::
https://codegolf.stackexchange.com/info/33196/loop-without-looping/33218#33218
Ответы
Ответ 1
В соответствии с Richter во втором выпуске CLR через С# (да, мне нужно обновить):
Страница 478
Для (CLR выключается) каждый метод Finalize получает приблизительно две секунды для возврата. Если метод Finalize не возвращается в течение двух секунд, CLR просто убивает процесс - не вызывается больше Finalize. Кроме того, если для вызова всех методов Finalize требуется больше 40 секунд, CLR просто убивает процесс.
Кроме того, как упоминает Servy, у него есть собственный поток.
Ответ 2
Финализатор не запускается в основном потоке. Финализатор имеет свой собственный поток, который запускает код, и это не поток переднего плана, который будет поддерживать приложение. Основной поток завершается эффективно сразу, и в этот момент поток финализатора просто выполняется столько раз, сколько получает шанс до того, как процесс будет сорван. Ничто не поддерживает программу.
Ответ 3
Сборщик мусора не является активной системой. Он работает "иногда" и в основном по требованию (например, когда все страницы, предлагаемые ОС, полны).
Большинство сборщиков мусора запускаются в подпотоке в стиле первого поколения. В большинстве случаев может потребоваться несколько часов, прежде чем объект будет переработан.
Единственная проблема возникает, когда вы хотите завершить работу программы. Однако это не проблема. Когда вы используете 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
и убийстве программы. Через пять секунд программа заканчивается (другими словами, сборщик мусора отказывается и просто освобождает всю память без учета финализаторов).