Re: [Boost-bugs] [Boost C++ Libraries] #3080: dynamic_cast returns 0 on polymorphic serialization with weak_ptr

Subject: Re: [Boost-bugs] [Boost C++ Libraries] #3080: dynamic_cast returns 0 on polymorphic serialization with weak_ptr
From: Boost C++ Libraries (noreply_at_[hidden])
Date: 2009-05-30 02:53:40


#3080: dynamic_cast returns 0 on polymorphic serialization with weak_ptr
----------------------------------------------------+-----------------------
  Reporter: Takatoshi Kondo <kondo_at_[hidden]> | Owner: ramey
      Type: Bugs | Status: new
 Milestone: Boost 1.40.0 | Component: serialization
   Version: Boost 1.39.0 | Severity: Problem
Resolution: | Keywords:
----------------------------------------------------+-----------------------

Comment(by Takatoshi Kondo <kondo_at_[hidden]>):

 I'm sorry for being confused.

 https://svn.boost.org/trac/boost/ticket/3080#comment:1 is not a sample
 that works correctly.

 The motivation of this sample is describe behavior of shared_ptr_hepler.

 {{{
 #!cpp

 56 class shared_ptr_helper {
 57 typedef std::map<const void *, shared_ptr<void> >
 collection_type;
 58 typedef collection_type::const_iterator iterator_type;
 59 // list of shared_pointers create accessable by raw pointer.
 This
 60 // is used to "match up" shared pointers loaded at different
 61 // points in the archive. Note, we delay construction until
 62 // it is actually used since this is by default included as
 63 // a "mix-in" even if shared_ptr isn't used.
 64 collection_type * m_pointers;

 snip ...

 111 public:
 112 template<class T>
 113 void reset(shared_ptr<T> & s, T * r){
 114 if(NULL == r){
 115 s.reset();
 116 return;
 117 }
 118 // get pointer to the most derived object. This is
 effectively
 119 // the object identifer
 120 const void * od = object_identifier(r);
 121
 122 if(NULL == m_pointers)
 123 m_pointers = new collection_type;
 124
 125 iterator_type it = m_pointers->find(od);
 126
 127 if(it == m_pointers->end()){
 128 s.reset(r);
 129 m_pointers->insert(collection_type::value_type(od,s));
 130 }
 131 else{
 132 s = static_pointer_cast<T>((*it).second);
 133 }
 134 }
 }}}

 The sample that reproduces bug is the following.
 https://svn.boost.org/trac/boost/attachment/ticket/3080/wps.cpp

 And I made more essential following sample(sp_mlt_base.cpp).

 {{{
 #!cpp
 #include <cassert>
 #include <fstream>
 #include <boost/shared_ptr.hpp>
 #include <boost/weak_ptr.hpp>
 #include <boost/serialization/serialization.hpp>
 #include <boost/archive/xml_oarchive.hpp>
 #include <boost/archive/xml_iarchive.hpp>
 #include <boost/serialization/nvp.hpp>
 #include <boost/serialization/export.hpp>
 #include <boost/serialization/shared_ptr.hpp>
 #include <boost/serialization/weak_ptr.hpp>

 struct Base1 {
     virtual ~Base1() {}
     // serialize
     friend class boost::serialization::access;
     template<class Archive>
     void serialize(Archive & /*ar*/, const unsigned int /* file_version
 */) {}
 };

 BOOST_CLASS_EXPORT(Base1)

 struct Base2 {
     virtual ~Base2() {}
     // serialize
     friend class boost::serialization::access;
     template<class Archive>
     void serialize(Archive & /*ar*/, const unsigned int /* file_version
 */) {}
 };

 BOOST_CLASS_EXPORT(Base2)

 struct Sub:public Base1, public Base2 {
     virtual ~Sub() {}
     boost::weak_ptr<Sub> wp_;

     // serialize
     friend class boost::serialization::access;
     template<class Archive>
     void serialize(Archive &ar, const unsigned int /* file_version */)
     {
         ar & BOOST_SERIALIZATION_BASE_OBJECT_NVP(Base1);
         ar & BOOST_SERIALIZATION_BASE_OBJECT_NVP(Base2);
         ar & BOOST_SERIALIZATION_NVP(wp_); // *1
     }
 };

 BOOST_CLASS_EXPORT(Sub)

 int main()
 {
     {
         // serialize
         boost::shared_ptr<Sub> s(new Sub);
         boost::shared_ptr<Base2> pb2(s);
         s->wp_ = s; // set weak_ptr. If not set, deserialize success.
         std::ofstream ofs("output.xml");
         assert(ofs);
         boost::archive::xml_oarchive oa(ofs);
         oa << boost::serialization::make_nvp("Base2", pb2);
     }
     {
         // de-serialize
         std::ifstream ifs("output.xml");
         assert(ifs);
         boost::archive::xml_iarchive ia(ifs);
         boost::shared_ptr<Base2> pb2;
         ia >> boost::serialization::make_nvp("Base2", pb2);
         // check
         // pb2's vptr is broken.
         assert(dynamic_cast<Sub *>(pb2.get()));
     }
 }

 }}}

 Please check it.

-- 
Ticket URL: <https://svn.boost.org/trac/boost/ticket/3080#comment:4>
Boost C++ Libraries <http://www.boost.org/>
Boost provides free peer-reviewed portable C++ source libraries.

This archive was generated by hypermail 2.1.7 : 2017-02-16 18:50:00 UTC