Derelict SFML destructor crashes

Mike Parker aldacron at gmail.com
Sun Dec 16 20:40:38 PST 2012


First, please take all Derelict trouble-shooting problems to the 
Derelict forums[1]. I never check the sfml forums. I do check the 
newsgroups regularly, but these newsgroups are not generally the 
place to look for help with Derelict problems. Plus, by posting 
in other places, you are making it more unlikely that future 
users with the same problem will find an answer.


On Sunday, 16 December 2012 at 17:20:55 UTC, Nekroze wrote:
>>> I am sorry if i am being dim but i thought that the sfml 
>>> objects are not GC objects so it will exist forever until i 
>>> call its destroy function so why cant this be done in the 
>>> destructor? Unless you mean the pointer is being destroyed 
>>> before the destructor is being called?

You are correct in that the sfImage instance is not GCed and will 
continue to stay resident in memory. But *your* Image class *is* 
GCed. You cannot, ever, rely on D destructors to clean up 
external resources. This is because you have no idea when, if, or 
in what order they will be called during runtime. They *will* be 
called when the program exits and the GC cleans up, but that is 
where you are running into your problem. See below.


> sfImage_destroy is purely a binding to a c function in a dll. 
> It has no knowledge of the GC or anything which is why the 
> image will live forever unless i call that function.
>
> SFML is a c++ OO based graphics library, in order to provide a 
> c binding they made a C wrapper around all the OO stuff so the 
> object, its all handled using C functions, needs to have its 
> destructor called manually with the C destroy functions. With 
> the D wrapper for this (Derelict3) there is no actual function 
> for these its just some kind of pass through binding to the dll 
> so the above, as far as i can understand, still holds true.
>
> This is why i have come to the belief that i should be 
> perfectly able to call this destroy function in the destructor 
> because what i am calling destroy on is an object that is 
> created in C++ but accessed through C functions which have just 
> been imported and bound to D names.

You have to understand that Derelict is a dynamic binding and not 
a static one. In this sort of binding, all of the functions you 
call are actually function pointers. When you call 
DerelictSFML2.load, Derelict is loading the shared library for 
you and making sure the function pointers are pointing to the 
write places. In a static binding where you would link with a 
static library, a Windows DLL import library, or directly with an 
shared object file on Posix systems, the shared library is loaded 
automatically and you call the functions normally rather than 
through pointers ("bound to D names", in other words).

Any call to load a library into memory should generally be 
matched by a call to unload it. All Derelict bindings include a 
module destructor that automatically unloads its shared library 
at program exit. So here's what's happening to you. When your 
main function exits, the runtime starts the cleanup process. It 
runs the module destructors *before* cleaning up the GC. So 
DerelictSFML2's module destructor is run, the CSFML2 library is 
unloaded from memory, then after that the GC's cleanup begins 
and, at some point, the destructor on your Image class instance 
is called. Only now, when you call sfImage_destroy the library 
was already unloaded by the module destructor so the function 
pointer is no longer valid. Boom! You have a crash.

Perhaps it would be ok for me to remove the module destructors 
and let the OS just free up the libraries when the process exits, 
but I'm not going to do that. Regardless, it doesn't change the 
fact that you should never, ever, ever rely on D class 
destructors for this sort of thing.


More information about the Digitalmars-d-learn mailing list