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

Subject: [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-25 13:26:35


#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
 Keywords: |
---------------------------------------------------+------------------------
 === Problem ===
 In multiple inheritance case, after de-serialization, failed to
 dynamic_cast from a data member polymorphic serialize via 2nd base class
 (Left) to subclass (Bottom).

 {{{
 #!cpp
         // check
         Left *pLeft = h2.mbl_.get();
         Bottom *pBottomFromLeft = dynamic_cast<Bottom *>(pLeft);

         Right *pRight = h2.mbr_.get();
         Bottom *pBottomFromRight = dynamic_cast<Bottom *>(pRight);

         assert(pBottomFromLeft); // Success
         assert(pBottomFromRight); // Fail. Comment out *1 and *2, it works
 corrctly.
 }}}

 === My analysis ===
 Class 'Bottom' has weak_ptr that point to itself. When weak_ptr member wp_
 exclude serialization, dynamic_cast is success.(Comment out *1 and *2
 lines.)

 I set break point (using gdb). => is position.

 {{{
 #!cpp
 class Holder {
 public:
     LeftSp mbl_; // shared_ptr<Left>
     RightSp mbr_; // shared_ptr<Right>

     Holder() {} // for serialize
     Holder(BottomSp l, BottomSp r):mbl_(l) ,mbr_(r) {} // for appli
 construct

     // serialize
     friend class boost::serialization::access;
     template<class Archive>
     void save(Archive &ar, const unsigned int /* file_version */) const
     {
         // polymophic serialize via shared_ptr
         ar << BOOST_SERIALIZATION_NVP(mbl_);
         // polymophic serialize via shared_ptr
         ar << BOOST_SERIALIZATION_NVP(mbr_);
     }
     template<class Archive>
     void load(Archive & ar, const unsigned int /* file_version */)
     {
         // polymophic de-serialize via shared_ptr
         ar >> BOOST_SERIALIZATION_NVP(mbl_);
         // polymophic de-serialize via shared_ptr
         ar >> BOOST_SERIALIZATION_NVP(mbr_);
 => }
     BOOST_SERIALIZATION_SPLIT_MEMBER()
 };
 }}}

 And, I printed below values.

 In assertion failed case, _vptr.Left is equal to _vptr.Right.

 {{{
 (gdb) p *mbl_.px
 $1 = {_vptr.Left = 0x8060ba8}
 (gdb) p *mbr_.px
 $1 = {_vptr.Right = 0x8060ba8}
 }}}

 But, success case (remove the member wp_'s serialization), _vptr.Left is
 not equal to _vptr.Right

 {{{
 (gdb) p *mbl_.px
 $1 = {_vptr.Left = 0x805d1e8}
 (gdb) p *mbr_.px
 $1 = {_vptr.Right = 0x805d1f8}
 }}}

 === Environment ===
 g++ (Gentoo 4.3.2-r3 p1.6, pie-10.1.5) 4.3.2
 Copyright (C) 2008 Free Software Foundation, Inc.
 This is free software; see the source for copying conditions. There is NO
 warranty; not even for MERCHANTABILITY or FITNESS FOR A PARTICULAR
 PURPOSE.

-- 
Ticket URL: <https://svn.boost.org/trac/boost/ticket/3080>
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