在垃圾收集期间从析构函数传递的消息

Joh*_*ohn 5 d

以下给我一个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...");
}
Run Code Online (Sandbox Code Playgroud)

以上产生:

收到:基本测试
析 构函数:c1手动删除
收到:c1手动删除
运行垃圾收集器...
析构函数
:c2收集垃圾收到:c2收集垃圾
捕获throwable:object.Error:访问冲突
退出主线程...

这有什么变通方法吗?
有没有办法让析构函数代码知道它是否被GC调用?
从析构函数传递的消息本质上是不安全的,例如,如果GC在共享消息框上具有互斥锁时非GC线程被冻结,那么如果GC发送到锁定的消息框,则GC可能会死锁?或者,所有线程解冻后,析构函数代码是否仅在扫描周期中发生?
析构函数引用线程本地存储是否安全,例如GC扫描周期是否可以在不同的线程中?

dsi*_*cha 5

我在这里看到两个可能相关的问题.首先,不允许从GC调用的析构函数引用子对象.

此外,未指定垃圾收集器为非引用对象调用析构函数的顺序.这意味着当垃圾收集器为具有引用垃圾收集对象的成员的类的对象调用析构函数时,这些引用可能不再有效.这意味着析构函数不能引用子对象.

其次,正如您所提到的,析构函数调用仅在所有线程恢复后才在扫描周期中进行.它们可以从一个不同的线程调用,而不是在它活着时拥有该对象的线程.桌面上有提议来解决这个问题,但到目前为止还没有实施.