18.07.2012 8:00, Mike Parker пишет:

Destructors are unreliable. There is no guarantee that a destructor will
be called before the garbage collector is terminated. When the program
exits, the runtime will call gc_term which will then call destructors on
any objects that haven't yet been cleaned up. But the order in which
those destructors are called is unpredictable. This is a recipe for all
sorts of problems.

Static class destructors and module destructors are more reliable in
that you know they will be called in a particular order. But, they are
called before the gc is terminated.

Your particular problem is this. Derelict-style bindings load shared
libraries dynamically via system calls. That means that every bound
function is actually a function pointer. The shared library is then
unloaded in a static module destructor. When DRuntime exits, it calls
all the module destructors *before* calling gc_term. So what's happening
is:

1. The module destructors are run
2. Derelict unloads the shared library, thereby causing all of the
function pointers into that library to become invalid.
3. gc_term is run
4. The destructor of one of your objects is called and it tries to call
a function from the Derelict binding, but since that function pointer is
no longer valid, you get a segfault.

When cleaning up resources in D, you should generally not rely on class
destructors to do so. You'll want to include some sort of process to
clean up everything yourself. What I tend to do is something like this:

========
void term()
{
     // initiate cleanup here
}

void main()
{
     scope(exit) term();
     init();
     run();
}
========

The scope(exit) will ensure that the cleanup is run regardless of how
the program exits. Every subsystem in my program will have term()
function or method that substitutes for a destructor. This works fine
and I have no problems with it.

Of course, you can still use destructors for scoped object instances in
cases where you want RAII inside a particular scope.

Thank you very much for your help! Now I undestand it - I've never used gc before.

Reply via email to