views:

575

answers:

4

I have 2 static objects in 2 different dlls:

An object Resources (which is a singleton), and an object User. Object User in its destructor has to access object Resources.

How can I force object Resources not to be destructed before object User?

+2  A: 

Global objects are destroyed when their corresponding DLL is unloaded. So as your 'User' dll is probably dependent of your 'Resource' dll, you are in trouble: 'resource' will always be destroyed before 'user'.

I'm also interested by a good answer to this question, if one exist. Until now, I'm using a cleanup function that must be called by application before it quits, and I only keep harmless code in destructors.

Jem
Arf, so actually what you mean is that a DLL may be unload while not all global variable are destructed? :/
yves Baumes
+1  A: 

I don't think you can change order of destruction of globals that are in different modules. Any chance of adding some reference counting?

sean e
+2  A: 

If you are able to put that 2 global variables in the same DLL it's not the same story. As told by Jem in its own reply, DLL detachement order is not guaranteed by the system. Therefore you may have a big problem when having 2 separated Dlls. I am not a Windows system guru, but having a look with google, I found msdn bloggers who tells they had the same issue with no good solution to address it.

I you are able to put them in one same DLL, according to me the solution is easier, in that case you don't need to address the "not garanteed DLL detachement order" issue (unsolvable as far as I understand).
But then you still need to address a new issue: global variable destruction order is not garanteed by the c++ language. But this one can be addressed:

you need to use some kind of reference couting. a boost::shared_ptr may do the trick.

Declare it global and define it that way:

boost::shared_ptr my_resource_ptr ( new Resource() ); // new operator is important here!

Then you need to modify your User implementation to store its own shared_ptr:

class User
{
    ...
    boost::share_ptr a_resource_ptr;
    ...
};

As long as all one of your User instance is not destroyed, those will 'retain' the Resource instance, and so prevent it from being prematuraly deleted, even though the global shared_ptr could have been destroyed.
The last User instance being destroyed will (undirectly) delete the Resource instance.

Whatever the reference counting you use, ComPtr, your own, it should do the trick.

yves Baumes
+1  A: 

In the case you really want to get 2 separated Dlls I may have some hints for you: you may consider the use of FreeLibrary() from Windows API. As stated by msdn FreeLibrary() decrements a reference counter for the Dll which is unloaded when the counter reaches 0.

Drawback: using FreeLibrary() implies you are loading it with LoadLibrary() (msdn link) and calling function from this library implies you are using the GetProcAddress() function, which may lead to really ugly code. And it may imply some change in your code too - as getting global variable poiting to the Dll's functions in order to store each functions' address ...

If you want to implement it:

  1. you must load&free the library from your main() function of your process,
  2. and also load and free the library from the Dll implenting the User class. Implement it in the DllMain() function for this Dll, when the reason is DLL_PROCESS_DETACH (see mdsn's DllMain link.

Thus it will unload the "Resource" library only once the "User" library have finish with it.

Have a try if you will and let tell me if it works as I never implemented it..

Ps: I've posta second answer to your question to get a meaningful separation between the two answers as I (try to) detail both of them. I don't want you to mix them up and get confused ...

yves Baumes