2011-04-23 8 views
5

다음은 Windows 32 비트, dmd.2.052, 플래그 없음에 대한 액세스 위반입니다. 소멸자가 가비지 수집기에서 실행할 때 메시지 상자가 프로세스에서 손상된 것 같습니다.가비지 수집 중 소멸자에서 전달되는 메시지

import std.stdio; 
import core.thread; 
import core.memory; 
import std.concurrency; 

class C 
{ 
    string m_str; 
    Tid m_receiverTid; 
    this(string s, Tid rt) { this.m_str = s; this.m_receiverTid = rt; } 
    ~this() { writeln("Destructor : ",this.m_str); 
       m_receiverTid.send(this.m_str); 
      } 
} 


void receiver() { 
     try { 
      while(true) { 
       receive((string s){writeln("Received: ",s);}); 
      } 
     } catch (Throwable th) { 
      writeln("Caught throwable: ",th.toString()); 
     } 
} 

void main() { 
    Tid receiverTid = spawn(&receiver); 

    receiverTid.send("Basic test"); 
    Thread.sleep(5_000_000); 

    C c1 = new C("c1 Manually deleted",receiverTid); 
    delete c1; 
    Thread.sleep(5_000_000); 

    { 
     C c2 = new C("c2 Garbage collected",receiverTid); 
    } 
    writeln("Running garbage collector..."); // This line needed to flush out the c2 root pointer. 
    GC.collect(); 
    Thread.sleep(5_000_000); 

    writeln("Exiting main thread..."); 
} 

는 위의 생산이에 대한 대안은

Received: Basic test
Destructor : c1 Manually deleted
Received: c1 Manually deleted
Running garbage collector...
Destructor : c2 Garbage collected
Received: c2 Garbage collected
Caught throwable: object.Error: Access Violation
Exiting main thread...

이 있습니까?
소멸자 코드가 GC에 의해 호출되는지 여부를 알 수있는 방법이 있습니까?
소멸자로부터 본질적으로 안전하지 않은 메시지 전달 중 (예 : 비 GC 스레드가 GC에 의해 고정되어있는 동안 공유 메시지 상자에 뮤텍스 잠금이 있으면 잠긴 메시지 상자로 보내면 GC가 교착 상태가 될 수 있습니까? 또는 소멸자 코드는 모든 스레드가 해동 된 후에 만 ​​스윕주기에 발생합니까?
소멸자가 스레드 로컬 저장소를 참조하는 것이 안전합니까? 예 : GC 스윕주기가 다른 스레드에있을 수 있습니까?

답변

5

관련이있을 수있는 두 가지 문제가 있습니다. 당신이 언급 모든 스레드가 재개 된 후 첫째, referencing subobjects from a destructor called by the GC is not allowed.

Furthermore, the order in which the garbage collector calls destructors for unreference objects is not specified. This means that when the garbage collector calls a destructor for an object of a class that has members that are references to garbage collected objects, those references may no longer be valid. This means that destructors cannot reference sub objects.

둘째, 소멸자 호출은 스윕 사이클에서 개최 않습니다. 객체가 살아있을 때 객체를 소유 한 스레드와 다른 스레드에서 호출 될 수 있습니다. 이 문제를 해결하기위한 제안이 있지만 지금까지 아무 것도 구현되지 않았습니다.