[Boost-bugs] [Boost C++ Libraries] #3604: Access violation on diamond inheritance

Subject: [Boost-bugs] [Boost C++ Libraries] #3604: Access violation on diamond inheritance
From: Boost C++ Libraries (noreply_at_[hidden])
Date: 2009-11-10 12:42:10


#3604: Access violation on diamond inheritance
---------------------------------+------------------------------------------
 Reporter: kondo@… | Owner: ramey
     Type: Bugs | Status: new
Milestone: Boost 1.41.0 | Component: serialization
  Version: Boost 1.40.0 | Severity: Problem
 Keywords: |
---------------------------------+------------------------------------------
 = phenomenon =
 When I serialize the sub-class via virtual base class,
 some BOOST_CLASS_EXPORT order makes access violation.

 main.cpp(attached file) reproduce these behavior on VC++ ver 9. Please
 check it.

 Classes structure is structure.png(attached file).

 If BOOST_CLASS_EXPORT order is Target, Sub1, the error doesn't occur.
 If BOOST_CLASS_EXPORT order is Sub1, Target, the error occurs.

 main.cpp
 {{{
 #!cpp
 #if 0
 // OK
 BOOST_CLASS_EXPORT(Target)
 BOOST_CLASS_EXPORT(Sub1)
 #else
 // NG
 BOOST_CLASS_EXPORT(Sub1)
 BOOST_CLASS_EXPORT(Target)
 #endif
 }}}

 = analysis =
 I checked the behavior of void_caster::recursive_register step by step.

 boost_1_40_0\libs\serialization\src\void_cast.cpp
 {{{
 #!cpp
 // implementation of void caster base class
 BOOST_SERIALIZATION_DECL(void)
 void_caster::recursive_register(bool includes_virtual_base) const {
     void_cast_detail::set_type & s
         = void_cast_detail::void_caster_registry::get_mutable_instance();

     s.insert(this);

     // generate all implied void_casts.
     void_cast_detail::set_type::const_iterator it;
     for(it = s.begin(); it != s.end(); ++it){
         if(* m_derived == * (*it)->m_base)
             new void_caster_shortcut( // match A
                 (*it)->m_derived,
                 m_base,
                 m_difference + (*it)->m_difference,
                 includes_virtual_base
             );
         if(* (*it)->m_derived == * m_base)
             new void_caster_shortcut( // match B
                 m_derived,
                 (*it)->m_base,
                 m_difference + (*it)->m_difference,
                 includes_virtual_base
             );
     }
 }}}

 ----
 OK Case

 r-level means recursive level(not so important).
 'No' means registration order(not internal order of container set).

 ||No||r-level||virtual base||Derived||Base||Action||!OverWrite||
 ||0||||false||Target||Sub2||-||||
 ||1||||false||Sub1||Mid1||-||||
 ||2||||false||Sub1||Mid2||-||||
 ||3||||false||Sub2||Mid1||match A Sub2 No.0,add No.4||||
 ||4||1||false||Target||Mid1||-||||
 ||5||||false||Sub2||Mid2||match A Sub2 No.0,add No.6||||
 ||6||1||false||Target||Mid2||-||||
 ||7||||true||Mid1||VBase||match A Mid1 No.1,add No.8||||
 ||||||||||||match A Mid1 No.3 add No.9||||
 ||||||||||||match A Mid1 No.4 add No.11||||
 ||8||1||true||Sub1||VBase||-||||
 ||9||1||true||Sub2||VBase||match A Sub2 No.0,add No.10||||
 ||10||2||true||Target||VBase||-||||
 ||11||2||true||Target||VBase||-||No.10||
 ||12||||true||Mid2||VBase||match A Mid2 No.2,add No.13||||
 ||||||||||||match A Mid2 No.5,add No.14||||
 ||||||||||||match A Mid2 No.6,add No.16||||
 ||13||1||true||Sub1||Vbase||-||No.8||
 ||14||1||true||Sub2||VBase||match A Sub2 No.0,add No.15||No.9||
 ||15||2||true||Target||VBase||-||No.10||
 ||16||1||true||Target||VBase||-||No.10||

 Result (focus on m_includes_virtual_base)

 values of s
 {{{
 #!cpp
 void_cast_detail::set_type & s
     = void_cast_detail::void_caster_registry::get_mutable_instance();
 }}}
 {{{
 [0] 0x004add48 t const
 boost::serialization::void_cast_detail::void_caster *
 [1] 0x004add7c t const
 boost::serialization::void_cast_detail::void_caster *
 [2] 0x004adb7c t const
 boost::serialization::void_cast_detail::void_caster *
 [3] 0x004adbb0 t const
 boost::serialization::void_cast_detail::void_caster *
 [4] 0x003981e0 {m_includes_virtual_base=true } const
 boost::serialization::void_cast_detail::void_caster *
 [5] 0x004adce0 t const
 boost::serialization::void_cast_detail::void_caster *
 [6] 0x004add14 t const
 boost::serialization::void_cast_detail::void_caster *
 [7] 0x00398298 {m_includes_virtual_base=true } const
 boost::serialization::void_cast_detail::void_caster *
 [8] 0x00397a18 {m_includes_virtual_base=false } const
 boost::serialization::void_cast_detail::void_caster *
 [9] 0x003943c8 {m_includes_virtual_base=false } const
 boost::serialization::void_cast_detail::void_caster *
 [10] 0x004adb48 t const
 boost::serialization::void_cast_detail::void_caster *
 [11] 0x00398350 {m_includes_virtual_base=true } const
 boost::serialization::void_cast_detail::void_caster *
 }}}

 ----
 NG Case
 ||No||r-level||vb||Derived||Base||Action||!OverWrite||
 ||0||||false||Sub1||Mid1||-||||
 ||1||||false||Sub1||Mid2||-||||
 ||2||||false||Target||Sub2||-||||
 ||3||||true||Mid1||VBase||match A Mid1 No.0,add No.4||||
 ||4||1||true||Sub1||VBase||-||||
 ||5||||true||Mid2||VBase||match A Mid2 No.1,add No.6||||
 ||6||1||true||Sub1||VBase||-||No.4||
 ||7||||false||Sub2||Mid1||match B Mid1 No.3,add No.8||||
 ||||||||||||match A Sub2 No.2,add No.10||||
 ||8||1||false||Sub2||VBase||match A Sub2 No.2,add No.9||||
 ||9||2||false||Target||VBase||-||||
 ||10||1||false||Target||Mid1||match B Mid1 No.3,add No.11||||
 ||11||2||false||Target||VBase||-||No.9||
 ||12||||false||Sub2||Mid2||match B Mid2 No.5,add No.13||||
 ||||||||||||match A Sub2 No.2,add No.15||||
 ||13||1||false||Sub2||VBase||match A Sub2 No.2,add No.14||No.8||
 ||14||2||false||Target||VBase||-||No.9||
 ||15||1||false||Target||Mid2||match B Mid2 No.5,add No.16||||
 ||16||2||false||Target||VBase||-||No.9||

 Result (focus on m_includes_virtual_base)
 {{{
 [0] 0x004adce0 t const
 boost::serialization::void_cast_detail::void_caster *
 [1] 0x004add14 t const
 boost::serialization::void_cast_detail::void_caster *
 [2] 0x004adb48 t const
 boost::serialization::void_cast_detail::void_caster *
 [3] 0x004adb7c t const
 boost::serialization::void_cast_detail::void_caster *
 [4] 0x00397a18 {m_includes_virtual_base=true } const
 boost::serialization::void_cast_detail::void_caster *
 [5] 0x004add48 t const
 boost::serialization::void_cast_detail::void_caster *
 [6] 0x004add7c t const
 boost::serialization::void_cast_detail::void_caster *
 [7] 0x00398190 {m_includes_virtual_base=false } const
 boost::serialization::void_cast_detail::void_caster *
 [8] 0x00398300 {m_includes_virtual_base=false } const
 boost::serialization::void_cast_detail::void_caster *
 [9] 0x00398540 {m_includes_virtual_base=false } const
 boost::serialization::void_cast_detail::void_caster *
 [10] 0x004adbb0 t const
 boost::serialization::void_cast_detail::void_caster *
 [11] 0x00398248 {m_includes_virtual_base=false } const
 boost::serialization::void_cast_detail::void_caster *
 }}}
 ----
 m_includes_virtual_base is different in OK case and NG case.

 Probably it is the reason of access violation.

 I think that there is a problem in void_caster::recursive_register
 algorithm.

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