From: colin AT fu DOT is DOT saga-u DOT ac DOT jp (Colin Peters) Subject: Atexit and DLLs 24 Feb 1998 14:59:15 -0800 Message-ID: <000901bd4105$c717a760$fa173185.cygnus.gnu-win32@gbird0.fu.is.saga-u.ac.jp> Mime-Version: 1.0 Content-Type: text/plain; charset="iso-8859-1" Content-Transfer-Encoding: 7bit To: "GNU-Win32" (Thanks to Andrey A. Smirnov for pointing this out) I have discovered a fascinating problem with loading and freeing dlls in Mingw32. This is probably not a problem in Cygwin32 because Cygwin32 doesn't call the __do_global_ctors function to initialize global objects inside the DLL. Basically the problem is this: You can load a DLL using LoadLibrary and call functions through pointers obtained with GetProcAddress, however if you unload the DLL with FreeLibrary your program will crash when it exits. What's happening is related to atexit. Inside __do_global_ctors (part of the libgcc library) all the global objects in the DLL are initialized (my entry code for DLLs calls this so that you can have global objects inside a DLL). It also calls atexit to register the __do_global_dtors function to destroy all global objects should the program exit (prematurely or otherwise). Very smart, but... My entry code also calls __do_global_dtors when the DLL is unloaded, so that is not a problem: all the global objects inside the DLL are nicely destroyed. If the program exits normally __do_global_dtors gets called twice, but it's smart enough to deal with that. However, if you unload the DLL using FreeLibrary then the function pointer added to the atexit list (the __do_global_dtors in the DLL) is no longer valid. The call to it inside the DLL entry code goes fine and destroys the objects, but the call that occurs because it was added to the atexit list results in a GPF. Even if __do_global_ctors didn't call atexit(__do_global_dtors) there would still be a problem with any DLL which called atexit and registered a function in the DLL. Any program which tried to load the DLL and free it later would crash on exit. Andrey proposed (and supplied code for) a version of atexit to be statically linked in the DLL itself (overriding the crtdll version). Although I don't like adding more code to the startup, it does seem to be the only reasonable way to make this work. Does anyone have anything to add? For example, does MS mention using atexit in DLLs in their documentation? Does registering a function with atexit in a dynamically loaded DLL do the right thing in MSVC? Is handling it this way in fact the right thing (i.e. perhaps atexit should be off limits for use in DLLs)? If MSVC does something automagical then perhaps there is a capability built into their library which we could exploit if we could figure out how to use it. Awaiting opinions, Colin. -- Colin Peters - colin at fu.is.saga-u.ac.jp -- Saga Univ. Dept. of Information Science -- http://www.geocities.com/Tokyo/Towers/6162/index.html -- http://www.fu.is.saga-u.ac.jp/~colin/index.html - For help on using this list (especially unsubscribing), send a message to "gnu-win32-request AT cygnus DOT com" with one line of text: "help".