Boost logo

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


I'm hitting an assert when I deserialize cycles of
shared_ptr<>s. I have the following class hierarchy:

  Base <-- Derived

Derived holds a shared_ptr<Other>, and Other holds a

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).



P.S. Attached is the source code illustrating the above
example. Here is the output:


  Base done
  Other done
 Derived done


  Base done
   Base done
const boost::archive::detail::basic_pointer_iserializer*
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.

#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;

    std::cout << std::string(sIndentLevel--, ' ') << mName << " done" << std::endl;

  static int sIndentLevel;
  char const * mName;

int Debug::sIndentLevel = 0;

// Base
class Base
    virtual ~Base() { }
    template<class Archive> void serialize(Archive & ar, const unsigned int)
      Debug d("Base");

// Derived
class Derived : public Base
    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
    void setBase(BaseRef base) { mBase = base; }

    template<class Archive> void serialize(Archive & ar, const unsigned int)
      Debug d("Other");
      ar & mBase;

    BaseRef mBase;


// 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());
    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, kalb at, bjorn.karlsson at, gregod at, wekempf at