Robert
Ramey <ramey <at> rrsd.com> writes:
>
>
Martin Lederhilger wrote:
>
> Hello Robert, hello Bogdan,
>
>
>
> I have quite the same problem (Exception multiple_code_instantiation
>
> thrown in basic_serializer_map.cpp at line 48) as Bogdan. It can be
>
> reproduced by changing
>
> the pointer type from polymorphic_base to polymorphic_derived2 in the
>
> original test_dll_exported.cpp example, which comes with the library.
>
> I think the problem is that when oa << BOOST_SERIALIZATION_NVP(rb2);
>
> is called, that the system registers an type in oserializer.hpp, which
>
> leads to creation of the singletons also in the executeable.
>
>
Ahhhh - a very useful hint. So the rule would be that if a class
>
is polymorphic is to be serialized through a pointer, it should ONLY
>
be done through a base class pointer? That is, if ALL polymorphic
>
base classes are abstract - this problem will never occur?
>
>
I'll have to think about this.
>
>
> I have this problem when serializing a shared_ptr<A> in class B in
>
> B.dll to an object of class A in A.dll.
>
>
>
> I tried to simply comment out this check, but it seems that I get
>
> problems with tracking later. I have a class hierarchy like this:
>
> C derives from B derives from A. A has a weak_ptr<A> to itself
>
> (something like boost::enable_shared_from_this). If I serialize an
>
> object of type C via a base pointer of type B the serialization walks
>
> like this: C::serialize, B::serialize, A::serialize, and again
>
> C::serialize (with a wrong this pointer - and it should not do that).
>
>
Hmmm - why should it not do that? You may have a cycle - but
>
the library handles that. Seems unrelated to the other problem.
>
>
> Maybe my second problem depends on the first one. I hope that my
>
> report can be of help.
>
>
>
> Thanks in advance for your answers,
>
>
And thanks for your useful information.
>
>
> Martin Lederhilger
>
Hello
Robert,
On
your suggestion I have run a few tests. I hope they help:
I
commented out the registration macro associated to the base class in
ExportDll.dll:
-
//BOOST_CLASS_EXPORT_IMPLEMENT(polymorphic_base)
To
make the example more realistic I modified the inheritance hierarchy as
follows:
class
polymorphic_base{};
class
polymorphic_derived1 : public polymorphic_base{};
class
polymorphic_derived2 : public polymorphic_derived1{};
I
added one integer data member to polymorphic_derived1 and polymorphic_derived2.
Here
are the results:
==================================================
Polymorphic
serialization through a pointer to polymorphic_base WORKS AS EXPECTED:
//
Save code -----------------------------
polymorphic_base *rb0 = new polymorphic_derived1(100);
polymorphic_base *rb1 = new polymorphic_derived1(10);
polymorphic_base *rb2 = new polymorphic_derived2(10,20);
oa << BOOST_SERIALIZATION_NVP(rb0);
oa << BOOST_SERIALIZATION_NVP(rb1);
oa << BOOST_SERIALIZATION_NVP(rb2);
//
Load code -----------------------------
polymorphic_base *rb0 = NULL;
polymorphic_base *rb1 = NULL;
polymorphic_base *rb2 = NULL;
ia >> BOOST_SERIALIZATION_NVP(rb0);
ia >> BOOST_SERIALIZATION_NVP(rb1);
ia >> BOOST_SERIALIZATION_NVP(rb2);
The
serialized content is presented below:
-
for polymorphic_xml_[io]archive
<?xml
version="1.0" encoding="UTF-8" standalone="yes"
?>
<!DOCTYPE
boost_serialization>
<boost_serialization
signature="serialization::archive" version="7">
<rb0
class_id="1" class_name="polymorphic_derived1"
tracking_level="1" version="0" object_id="_0">
<polymorphic_base
class_id="0" tracking_level="0"
version="0"></polymorphic_base>
<m_d1_>100</m_d1_>
</rb0>
<rb1
class_id_reference="1" object_id="_1">
<polymorphic_base></polymorphic_base>
<m_d1_>10</m_d1_>
</rb1>
<rb2
class_id="2" class_name="polymorphic_derived2"
tracking_level="1" version="0" object_id="_2">
<polymorphic_derived1
object_id="_3">
<polymorphic_base></polymorphic_base>
<m_d1_>20</m_d1_>
</polymorphic_derived1>
<m_d2_>10</m_d2_>
</rb2>
</boost_serialization>
-
for polymorphic_text_[io]archive
22
serialization::archive 7 1 20 polymorphic_derived1 1 0
0
0 0 100 1
1
10 2 20 polymorphic_derived2 1 0
2
3
20 10
==================================================
Polymorphic
serialization through a pointer to polymorphic_derived1 (i.e. the class in the
middle of the hierarchy) FAILS WITH THE SAME EXCEPTION thrown about multiple
registration (see the beginning of this thread).
==================================================
What
is worrisome though, isomorphic serialization of polymorphic_derived1 as an
object followed by polymorphic serialization through a pointer to the base
class FAILS WITH ACCESS VIOLATION:
//
Save code -----------------------------
polymorphic_derived1 rb0(100);
polymorphic_base *rb1 = new polymorphic_derived1(10);
polymorphic_base *rb2 = new polymorphic_derived2(10,20);
oa << BOOST_SERIALIZATION_NVP(rb0);
oa << BOOST_SERIALIZATION_NVP(rb1);
oa << BOOST_SERIALIZATION_NVP(rb2);
//
Load code -----------------------------
polymorphic_derived1 rb0;
polymorphic_base *rb1 = NULL;
polymorphic_base *rb2 = NULL;
ia >> BOOST_SERIALIZATION_NVP(rb0);
ia >> BOOST_SERIALIZATION_NVP(rb1);
ia >> BOOST_SERIALIZATION_NVP(rb2);
The
code above fails in basic_iarchive.cpp(line 469) with access violation (bpis is
0).
if(! tracking){
bpis_ptr->load_object_ptr(ar, t, co.file_version);
}
The
serialized content is presented below:
-
using polymorphic_xml_[io]archive
<?xml
version="1.0" encoding="UTF-8" standalone="yes"
?>
<!DOCTYPE
boost_serialization>
<boost_serialization
signature="serialization::archive" version="7">
<rb0
class_id="0" tracking_level="0" version="0">
<polymorphic_base
class_id="1" tracking_level="0"
version="0"></polymorphic_base>
<m_d1_>100</m_d1_>
</rb0>
<rb1
class_id_reference="0" object_id="_0">
<polymorphic_base></polymorphic_base>
<m_d1_>10</m_d1_>
</rb1>
<rb2
class_id="2" class_name="polymorphic_derived2" tracking_level="1"
version="0" object_id="_1">
<polymorphic_derived1
object_id="_2">
<polymorphic_base></polymorphic_base>
<m_d1_>20</m_d1_>
</polymorphic_derived1>
<m_d2_>10</m_d2_>
</rb2>
</boost_serialization>
-
using polymorphic_text_[io]archive
22
serialization::archive 7 0 0 0 0 100 0
0
10 2 20 polymorphic_derived2 1 0
1
2
20 10
==================================================
Isomorphic
serialization of a class not related to the hierarchy as an object followed by
polymorphic serialization through a pointer to the base class WORKS AS EXPECTED.
==================================================
I
am looking forward to hearing your conclusions.
Thank
you,
Bogdan