Hi there,
Using the boost::serialization library, I'm hitting an
assert while deserializing. It happens only in a specific
set of circumstances requiring a shared_ptr to an abstract
base class.
Class "Derived" is derived from class "AbstractBase" which
is abstract. I'm serializing two objects which are of type
shared_ptr<AbstractBase> that point to objects of type
Derived. After the two shared_ptr's are serialized to disk,
when I read them back in I hit an assert in
basic_iarchive.cpp: "Assertion `new_cid == cid' failed".
This assert happens on the second object only.
As far as I can tell from the serialization documentation, I
am using the appropriate BOOST_CLASS_EXPORT() line for the
derived class, as well as registering the base-derived
relationship with base_object(), and I even threw in a
couple of BOOST_SERIALIZATION_SHARED_PTR() calls for good
measure although I don't think they do anything in my
environment.
Two additional pieces of information:
- If the base class is not abstract, but I still use
BOOST_IS_ABSTRACT(), I get the same assert. This might
indicate that some necessary polymorphism code isn't being
generated as a result of declaring the class abstract.
- If I serialize the pointers directly instead of using
shared_ptr, it does not hit the assert.
I have a workaround for this problem: it works as expected
if I define the load_construct_data() template function for
the base class do to nothing (assert), instead of using the
BOOST_IS_ABSTRACT() macro.
Attached is the minimal code to reproduce the problem. I'm
using boost 1.35.0 with gcc 3.3.5 on Linux (RHEL4). Is there
something I'm missing to make this work?
Thanks in advance,
Ult
#include <fstream>
#include
#include
#include
#include
#include
class AbstractBase
{
public:
AbstractBase() : mInt(-1) { }
virtual ~AbstractBase() { }
virtual void func() const = 0;
template<class Archive> void serialize(Archive & ar, const unsigned int)
{
ar & mInt;
}
int mInt;
};
BOOST_IS_ABSTRACT(AbstractBase);
BOOST_SERIALIZATION_SHARED_PTR(AbstractBase);
BOOST_CLASS_IMPLEMENTATION(AbstractBase, boost::serialization::object_serializable);
class Derived : public AbstractBase
{
public:
Derived() : mInt2(-2) { }
void func() const { }
template<class Archive> void serialize(Archive & ar, const unsigned int)
{
ar & boost::serialization::base_object<AbstractBase>(*this);
ar & mInt2;
}
int mInt2;
};
BOOST_CLASS_EXPORT(Derived);
BOOST_SERIALIZATION_SHARED_PTR(Derived);
BOOST_CLASS_IMPLEMENTATION(Derived, boost::serialization::object_serializable);
int main(int /* argc */, char * /* argv */[])
{
char const * fname = "abstract.out";
boost::shared_ptr<AbstractBase> baseA(new Derived());
boost::shared_ptr<AbstractBase> baseB(new Derived());
{
std::ofstream ofs(fname, std::ios::out | std::ios::binary);
boost::archive::text_oarchive oa(ofs);
oa & baseA;
oa & baseB;
}
{
std::ifstream ifs(fname, std::ios::in | std::ios::binary);
boost::archive::text_iarchive ia(ifs);
ia & baseA;
std::cout << "The following line asserts:" << std::endl;
ia & baseB; // Assertion `new_cid == cid' failed
// Full text of assert:
//
// /dev/libs/boost_1_35_0/libs/serialization/src/basic_iarchive.cpp:432: const boost::archive::detail::basic_pointer_iserializer* boost::archive::detail::basic_iarchive_impl::load_pointer(boost::archive::detail::basic_iarchive&, void*&, const boost::archive::detail::basic_pointer_iserializer*, const boost::archive::detail::basic_pointer_iserializer*(*)(const boost::serialization::extended_type_info&)): Assertion `new_cid == cid' failed.
}
}