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-31 06:35:43


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

  * status: closed => reopened
  * resolution: worksforme =>

Comment:

 == Result of test_zmisc.cpp ==
 === On VC++ 9.0.21022.8 RTM ===
 Compile successed.

 Run failed. Access violation occured. pb2_1 is incorrect.

 === On g++ (Gentoo 4.3.2-r3 p1.6, pie-10.1.5) 4.3.2. ===
 Compile successed.
 Run failed. Access violation occured. pb2_1 is incorrect.

 ----
 Same result.

 I think that these compilers are comparatively new, and major.

 Could you check your sample and my sample using these compiler?

 == My analysis ==
 pb2(original data)'s !__vfptr point to vftable for Base2.

 pb2_1(deserialized)'s !__vfptr point to vftavble for Base1.

 pb2_1's !__vfptr should point to vftable for Base2.

 Why does pb2_1's !__vfptr point to vftable for Base1.

 The reseason is following...

 {{{
 #!cpp
    template<class T>
     void reset(shared_ptr<T> & s, T * r){
         if(NULL == r){
             s.reset();
             return;
         }
         // get pointer to the most derived object. This is effectively
         // the object identifer
         const void * od = object_identifier(r);

         if(NULL == m_pointers)
             m_pointers = new collection_type;

         iterator_type it = m_pointers->find(od);

         if(it == m_pointers->end()){
             s.reset(r);
             m_pointers->insert(collection_type::value_type(od,s)); //
 point1
         }
         else{
             s = static_pointer_cast<T>((*it).second); // point2
         }
     }
 }}}
 https://svn.boost.org/trac/boost/browser/tags/release/Boost_1_39_0/boost/archive/shared_ptr_helper.hpp

  1. When m_wp deserialize, program passed point1.
  2. When pb2_1 deserialize, program passed point2.Because they point to
 same object.

 After step1, type information was lost. Because the container m_pointers
 type is shared_ptr<void>.

 In step2, it is impossible to distinguish that (*it).second is instance of
 'Sub' or instance of 'Base2'.

 Currently, member function reset() considers (*it).second to
 shared_ptr<Base2>, based on type T.

 Unfortunately the real object type is 'Sub'.

 After all, writing position for the desirializing data was shifted. And
 pb2_1 was broken.

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