
martin.ecker@tab.at wrote:
Hi,
<snip my comments on how to make sure all the global objects, such as type info and void caster objects, are always unique in a process>
Robert Ramey wrote:
Wouldn't this require that the first DLL loaded be the last one to be unloaded?
No. The order of loading/unloading DLLs doesn't matter. The first time a DLL is loaded that contains a BOOST_CLASS_EXPORT (and with it a number of global objects, such as type info), the global objects that need to be registered with the global registries and maps are created for the first time. Since they are reference counted, these process- wide unique, global objects only get destroyed when the last reference to them is released - for example, when the last DLL that uses them gets unloaded.
What I'm worried about are the virtual function calls routed through the base class vtable. The first object created has addresses in its vtable which point to the DLL that loaded it. Multiple entries would have different vtables each pointing to an address in a different DLL. If one DLL gets unloaded but the vtable remains in memory one is going to get a crash (if you're lucky) when makinga call through that base class instance. Hence my view that the first DLL to be loaded would have to be the last unloaded.
then -with the current use of (effectively global) static member variables in e.g. pointer_iserializer - you _will_ get multiple objects registered in the global registries and maps. There's nothing you can do about that (at least not on Windows; I believe with the Linux loader this problem does not occur). Throwing an exception if this happens, makes using Boost.Serialization with DLLs impossible.
This would make it an illegal detectable error to include the
serialization
of a given type in different DLLS and have those DLLS simultaneously loaded.
But there's nothing you can do about it. As soon as serialization code, in particular some global objects such as type info, are in a header file and that header file is included in code in multiple DLLs, you _will_ definitely get multiple copies of these objects (on Windows at least).
Its not clear to me that its an unavoidable problem. Just including the header for a serializable type won't trigger inclusion of the indicated static variables. One has to include archive code and instantiate it for the specific serializable type by invoking and << or >> operator on it. I don't believe the problem would ever arise if archve headers were included in only one DLL.
That's why my proposal is to let these global objects only be some kind of smart reference and have the "real" global objects that need to be unique for the running process be created by the Boost.Serialization DLL only once. Currently they are potentially created multiple times in the above scenario (i.e. serialization code in a header file that is included by code in multiple DLLs).
I understand the proposal. I don't think it would completely address the problem.
Although its a user issue, I would think that including the same code in different DLLS which are to be simultaneiously loaded defeats the whole
point of DLLS in the first place - to avoid having memory loaded with dead (or sleeping) code.
I agree with this. But because of the way the Windows DLL loader works in combination with global variables declared in C++ header files that are included by code in multiple DLLs, you cannot prevent having multiple instances of global variables.
This is what I'm not so sure about. However, avoid the problem would require some attention to code module organization which could be a problem for some people. Robert Ramey