Boost logo

Boost :

Subject: [boost] [Serialization] (Commented) assertion when using types in multiple DLLs on Windows (Ticket #3934 and #4394)
From: Martin B. (0xCDCDCDCD_at_[hidden])
Date: 2011-12-13 10:19:10


[Serialization] (Commented) assertion when using types in multiple DLLs
on Windows (Ticket #3934 and #4394)
-----------------------------------

## Problem:

We were using boost serialization in a DLL that is "statically" loaded
into our main application. We are using Boost 1.44 and the serialization
library as a DLL. (boost_serialization-vc80-mt-gd-1_44.dll)

Now, the serialized types that we are using in this DLL have also been
pulled into the main application -- that is, the .h+.cpp files of these
types are included and linked in the exe as well as in the DLL project.
(But the types are used independently in the exe and the dll module.)

In Boost 1.44 this leads to a runtime assertion in void_cast.cpp[1_44_0,
line 230].

## Investigation:

Since this code is in the function called
void_caster::recursive_register I *assume* that this is the point where
the types registered for serialization are registered with the library.

I have found that this runtime assert was commented out in release 1.45
and all subsequent versions:

     std::pair<void_cast_detail::set_type::const_iterator, bool> result;
     // comment this out for now.
     result = s.insert(this);
     //assert(result.second);

*Apparently* this was done in response to trac ticket #4394[1], at least
judging from the comment Robert Ramey added to the ticket:

> For now I'm going to comment out the assert.
> When I have time, I'll likely re-enable it with a way to override it.

I can only assume that ticket #3934[2] refers to the same or a similar
problem.

## Issue with the conclusion in #4394

Robert writes in his comment:

> The problem is that the way the code is structured,
> you'll have multiple instances of some functions.
> The best way would be eliminate the source of the
> problem by structuring code like this:
> ...
>

and he proposes to move the `template<class Archive> void serialize`
function of the classes from the header file into the cpp file.

However, *our* code already does this, and we get this assertion
regardless. The reason I suspect is that both the main module code as
well as the DLL module code are calling into the recursive_register
function to register the type, and since the code for the class is
(identically) duplicated in the DLL as well as in the executable,
obviously it is registered twice.

## Question: Am I correct?

So, the first question obviously is whether I'm correct in my analysis.

I.e., the `assert(result.second);`that is currently commented out can
*never* work properly for types that live in two modules (DLLs) in the
same process and Boost:serialization is used as DLL.

## Question: Any harm done?

Secondly, is there any adverse effect of a type being registered twice
with the serialization DLL? What will happen on unload? Is it possible
the type is unloaded too early because of this setup?

Note: What about accidentally identical type keys for actually different
types in different DLLs?

## Question: Solutions?

What is a proper solution? Should we use dllexport types, so that the
type is only registered once per process? What else?

Robert, I hope you can chime in on this. I'll try to add a link to this
mail to the trac issue #4394.

cheers,
Martin

[1] : https://svn.boost.org/trac/boost/ticket/4394
[2] : https://svn.boost.org/trac/boost/ticket/3934


Boost list run by bdawes at acm.org, gregod at cs.rpi.edu, cpdaniel at pacbell.net, john at johnmaddock.co.uk