Subject: Re: [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-14 06:59:34
On 14.12.2011 09:19, Martin B. wrote:
> On 14.12.2011 09:03, Martin B. wrote:
>> On 13.12.2011 18:22, Robert Ramey wrote:
>>> Martin B. wrote:
>>>> [Serialization] (Commented) assertion when using types in multiple
>>> (...) (...)
>>>> ## Question: Solutions?
>>> I would like to see you invest some more effort to see
>>> exactly where the extra registration comes from.
>> Well, see my call-stack above and I'll dump a sourcecode sketch below.
>> This does reproduce the thing for me, but other that ignoring the assert
>> (upgrading to boost 1.48) I haven't tried any approaches yet.
> Okay. Now, for this my testproject, I have been able to make it "just
> work" without the assertion by:
> 1. Removing the Types.cpp file from the executable (this will obviously
> initially give an unresolved external warning for Derived::* members)
> 2.) Make Derived a DLL export class, that is:
> class DLL_API Derived : ...
> with the usual (...)
> To my surprise it compiles, links, and runs correctly. (And the type is
> only registered once, namely from the DLL.)
> Now I'll just have to check if this solution can be applicable for our
> real projects, where we currently use BOOST_CLASS_EXPORT() instead of
> the split versions and we have a multitude of derived classes.
> So maybe the assertion made sense after all. (Though I think this should
> be configurable on a type by type basis should it ever be reenabled.)
OK, we have now adapted our real project types and it seems it's working
So, to summarize:
* The notification *makes* kind of sense, although it really isn't an
error but a nice warning and so the *unconditional* assert is rather
inappropriate I think.
* I guess the situation as it stands with the disabled assert is better
that the situation before with the unconditionally enabled assert. For
future improvements, I think that the BOOST_CLASS_EXPORT_* macros need
to provide a way to specify the desired checking level on a case by case
basis. (And the appropriate documentation for the firing assertion.)
* Making these Types DLL-exported and defining their implementation only
in the DLL worked for us, and in general, should probably work for most
types where this problem occurs, because in this context you already
have the situation of multiple DLLs+EXE, and you're just moving the
implementation of the type to a single place.
* [Speculation on my part:] If the types live in a static lib that is
used by different modules of the same process, things do get more
complicated, as it then should be more difficult to DLL-export the
types. But maybe one could work around this by not using the
serialization lib as a DLL but instead as a static lib. (Obviously would
lead to code bloat, but you're already living with duplicated
implementation code for the types in each module in this case anyway.)
: Wrt. "not an error" - The assertion was harmless for our code, but
the situation could (I have not tested it) be potentially disastrous for
dynamically loaded and unloaded DLLs that use the same types as another
module in the process. If I understood correctly, if the serialization
registration is done twice for a type, the first DLL to use it and being
unloaded will unregister the type, thus breaking serialization for this
type for all other modules. I haven't reproduced this, so it's largely
hypothetical at this point (are there any open tickets wrt. this?). I'm
also still unsure if only those types that use BOOST_CLASS_EXPORT are
affected by this problem.
Boost list run by bdawes at acm.org, gregod at cs.rpi.edu, cpdaniel at pacbell.net, john at johnmaddock.co.uk