|
Boost Users : |
Subject: [Boost-users] [serialization] Assertion failure with shared_ptr cycles
From: Ult Mundane (umundane_at_[hidden])
Date: 2008-10-29 17:01:07
Hi,
I'm hitting an assert when I deserialize cycles of
shared_ptr<>s. I have the following class hierarchy:
Base <-- Derived
Other
Derived holds a shared_ptr<Other>, and Other holds a
shared_ptr<Base>.
I have an instance of Derived that points to an instance of
Other, which in turn points back to the Derived instance (as
a Base pointer). The serialization goes as expected. On
deserialization, however, the Base::serialize() and
Derived::serialize() are called repeatedly, crashing after
the third time -- Other::serialize() is never called.
This problem only happens when the cycle includes a pointer
to a base class -- a straightforward a -> b -> a cycle works
as expected.
Has anyone else experienced this or found a workaround? It
happens in both boost 1.36 and 1.37.0 beta1. I'm using gcc
(3.3.5, 3.4.6, and 4.3.2).
Thanks,
Ult
P.S. Attached is the source code illustrating the above
example. Here is the output:
Serializing...
Derived
Base
Base done
Other
Other done
Derived done
Deserializing...
Derived
Base
Base done
Derived
Base
Base done
Derived
cycles:
./boost_1_37_0_beta1/libs/serialization/src/basic_iarchive.cpp:436:
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.
Aborted
#include <fstream>
#include <iostream>
#include <boost/archive/text_oarchive.hpp>
#include <boost/archive/text_iarchive.hpp>
#include <boost/serialization/shared_ptr.hpp>
#include <boost/serialization/is_abstract.hpp>
#include <boost/serialization/export.hpp>
// Forward declarations
class Base;
class Derived;
class Other;
typedef boost::shared_ptr<Base> BaseRef;
typedef boost::shared_ptr<Derived> DerivedRef;
typedef boost::shared_ptr<Other> OtherRef;
// For debug output
struct Debug
{
Debug(const char * name) : mName(name)
{
std::cout << std::string(++sIndentLevel, ' ') << mName << std::endl;
}
~Debug()
{
std::cout << std::string(sIndentLevel--, ' ') << mName << " done" << std::endl;
}
static int sIndentLevel;
char const * mName;
};
int Debug::sIndentLevel = 0;
// Base
class Base
{
public:
virtual ~Base() { }
template<class Archive> void serialize(Archive & ar, const unsigned int)
{
Debug d("Base");
}
};
// Derived
class Derived : public Base
{
public:
void setOther(OtherRef other) { mOther = other; }
template<class Archive> void serialize(Archive & ar, const unsigned int)
{
Debug d("Derived");
ar & boost::serialization::base_object<Base>(*this);
// This line is executed three times before a crash on deserialzation
ar & mOther;
// Code after here is never executed on deserialization
}
OtherRef mOther;
};
// Other
class Other
{
public:
void setBase(BaseRef base) { mBase = base; }
template<class Archive> void serialize(Archive & ar, const unsigned int)
{
Debug d("Other");
ar & mBase;
}
BaseRef mBase;
};
BOOST_CLASS_EXPORT(Derived);
// main
int main(int /* argc */, char * /* argv */[])
{
char const * fname = "cycles.text_archive";
std::cout << std::endl << "Serializing..." << std::endl << std::endl;
{
DerivedRef derived(new Derived());
OtherRef other(new Other());
derived->setOther(other);
other->setBase(derived);
std::ofstream ofs(fname, std::ios::out | std::ios::binary);
boost::archive::text_oarchive oa(ofs);
oa & derived;
}
std::cout << std::endl << "Deserializing..." << std::endl << std::endl;
{
Derived derivedCopy;
std::ifstream ifs(fname, std::ios::in | std::ios::binary);
boost::archive::text_iarchive ia(ifs);
ia & derivedCopy;
}
}
Boost-users list run by williamkempf at hotmail.com, kalb at libertysoft.com, bjorn.karlsson at readsoft.com, gregod at cs.rpi.edu, wekempf at cox.net