가비지 수집기는 여기서 무한 루프를 어떻게 피합니까?


101

다음 C # 프로그램을 살펴보면 루프없이 루프를 만들기위한 답변으로 codegolf에 제출했습니다.

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

이 프로그램은 내 검사에서 무한 루프처럼 보이지만 수천 번 반복 실행 된 다음 프로그램이 오류없이 성공적으로 종료됩니다 (오류가 발생하지 않음). P최종적으로 종료자가 호출되지 않는 것이 사양 위반 입니까?

분명히 이것은 결코 나타나지 않아야하는 어리석은 코드이지만 프로그램이 어떻게 완료 될 수 있는지 궁금합니다.

원본 코드 골프 게시물 :: /codegolf/33196/loop-without-looping/33218#33218


49
나는 이것을 실행하는 것이 두렵다.
Eric Scherrer

6
종료자가 호출되지 않은 것은 확실히 유효한 동작 영역 내에 있습니다 . 나는 그것이 수천 번의 반복을 실행하는 것이 왜 귀찮은 지 모르겠지만, 제로 호출을 기대할 것입니다.

27
CLR은 종료 자 스레드가 작업을 완료 할 수 없도록 보호합니다. 2 초 후에 강제 종료됩니다.
Hans Passant 2014

2
따라서 제목에있는 귀하의 질문에 대한 진정한 대답은 무한 루프를 40 초 동안 실행 한 다음 종료함으로써 피하는 것입니다.
Lasse V. Karlsen 2014

4
그것을 시도해 보면 프로그램은 어떤 일이 있어도 2 초 후에 모든 것을 죽이는 것 같습니다. 당신이 스레드를 산란을 계속하면 실제로는 :) 이상 꽤 지난 것
마이클 B

답변:


110

C #을 통한 CLR의 두 번째 버전에서 Richter에 따라 (예, 업데이트해야 함) :

478 권

(CLR이 종료되고 있음)의 경우 각 Finalize 메서드는 반환하는 데 약 2 초가 걸립니다. 경우 의 Finalize 방법은 2 초 내에 반환하지 않습니다, CLR은 그냥 프로세스를 종료하지 - 더 이상 의 Finalize 메소드가 호출됩니다. 또한 모든 개체의 Finalize 메서드 를 호출하는 데 40 초 이상 걸리면 CLR이 프로세스를 종료합니다.

또한 Servy가 언급했듯이 자체 스레드가 있습니다.


5
이 코드의 각 finalize 메서드는 개체 당 40 초 미만이 소요됩니다. 새 개체가 생성 된 다음 마무리 자격이 있다는 것은 현재 종료 자와 관련이 없습니다.
Jacob Krall 2014

2
이것은 실제로 작업을 완료하는 것이 아닙니다. 종료시 비워지는 Feachable 큐에 대한 시간 제한도 있습니다. 이 코드가 실패한 이유는 해당 대기열에 새 개체를 계속 추가합니다.
Hans Passant 2014

이것에 대해 생각하면 "또한 모든 개체의 Finalize 메서드를 호출하는 데 40 초 이상 걸리면 CLR이 프로세스를 종료 할뿐입니다."와 같이 분리 가능한 대기열을 비우는 것이 아닙니다.
Eric Scherrer

23

종료자는 주 스레드에서 실행되지 않습니다. 종료 자에는 코드를 실행하는 자체 스레드가 있으며 애플리케이션 실행을 유지하는 포 그라운드 스레드가 아닙니다. 주 스레드는 즉시 효과적으로 완료되며,이 시점에서 종료 자 스레드는 프로세스가 해체되기 전에 가능한 한 여러 번 실행됩니다. 프로그램을 유지하는 것은 없습니다.


메인 스레드가 살아 있지 않아 프로그램이 종료 된 지 40 초 후에 종료자가 완료되지 않으면 종료되고 프로세스가 종료됩니다. 이것은 오래된 값이지만 Microsoft는 지금까지 실제 숫자 또는 전체 알고리즘을 조정했을 수 있습니다. Se blog.stephencleary.com/2009/08/finalizers-at-process-exit.html
Lasse V. Karlsen

@ LasseV.Karlsen 문서화 된 언어 동작입니까, 아니면 단순히 MS가 구현 세부 사항으로 종료자를 구현하기로 선택한 방법입니까? 나는 후자를 기대할 것이다.
Servy

후자도 기대합니다. 내가 본이 동작에 대한 가장 공식적인 참조는 위의 Eric이 Jeffrey Richter의 C #을 통한 CLR 책에서 그의 답변에 게시 한 내용입니다.
Lasse V. Karlsen 2014

8

가비지 수집기는 활성 시스템이 아닙니다. 그것은 "때때로"그리고 대부분 수요에 따라 실행됩니다 (예 : OS에서 제공하는 모든 페이지가 가득 찬 경우).

대부분의 가비지 수집기는 하위 스레드에서 1 세대와 유사한 방식으로 실행됩니다. 대부분의 경우 개체를 재활용하는 데 몇 시간이 걸릴 수 있습니다.

프로그램을 종료하려는 경우에만 문제가 발생합니다. 그러나 그것은 실제로 문제가 아닙니다. killOS 를 사용할 때 정중하게 프로세스를 종료하도록 요청합니다. 그러나 프로세스가 활성 상태로 유지 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 초 후에 프로그램이 종료됩니다 (즉, 가비지 수집기가 포기하고 종료자를 고려하지 않고 모든 메모리를 해제합니다).


이것은 완전히 다른 이유로 인터랙티브 csharp가 폭발하는 것이 매력적입니다. 원래 프로그램 스 니펫에는 콘솔 쓰기 줄이 없었습니다.이 코드도 종료되는지 궁금합니다.
Michael B

@MichaelB : 이것도 테스트했습니다 (아래 주석 참조). 5 초 동안 기다렸다가 종료됩니다. 첫 번째 P인스턴스의 종료자가 단순히 시간 초과 되었다고 생각합니다 .
Willem Van Onsem 2014
당사 사이트를 사용함과 동시에 당사의 쿠키 정책개인정보 보호정책을 읽고 이해하였음을 인정하는 것으로 간주합니다.
Licensed under cc by-sa 3.0 with attribution required.