Boost logo

Boost Users :

Subject: Re: [Boost-users] [serialization] Assertion failure with shared_ptrcycles
From: Robert Ramey (ramey_at_[hidden])
Date: 2008-10-30 05:21:20


A couple of suggestions.

a) Make Base abstract by including something like
virtual ~Base() = 0; This won't address this problem
but it can catch accidental "slicing" in other cases.

b) The default behavior is to track addresses (thereby
detecting cycles, only if a type is serialized through
a pointer. Since this doesnt' occur in this program,
cycles won't be detected. use serialization traits
to set "serialization tracking" always on for the
type Base.

Robert Ramey

Ult Mundane wrote:
>> 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 mailing list
>> Boost-users_at_[hidden]
>> http://lists.boost.org/mailman/listinfo.cgi/boost-users


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