Как сборщик мусора избегает бесконечного цикла здесь?

Рассмотрим следующую программу на С#, я отправил ее на 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 и убийстве программы. Через пять секунд программа заканчивается (другими словами, сборщик мусора отказывается и просто освобождает всю память без учета финализаторов).