/////////1/////////2/////////3/////////4/////////5/////////6/////////7/////////8 // test_enable_shared_from_this.cpp // (C) Copyright 2002 Robert Ramey - http://www.rrsd.com . // Use, modification and distribution is subject to the Boost Software // License, Version 1.0. (See accompanying file LICENSE_1_0.txt or copy at // http://www.boost.org/LICENSE_1_0.txt) // This demonstrates a problem with boost::serialization and boost::enable_shared_from_this. // (boost version 1.53) // See boost TRAC ticket #9567 // // Given the following class structure: // Base is a simple class // Derived inherits from Base // Derived also inherits from boost::enable_shared_from_this // Base and Derived implement boost::serialization // // When deserializing an instance of Derived into a vector of boost::shared_ptr: // Base and Derived members are reconstructed correctly. // Derived::shared_from_this() works as expected. // // But when deserializing an instance of Derived into a vector of boost::shared_ptr: // Base and Derived members are still reconstructed correctly. // Derived::shared_from_this() throws a bad_weak_ptr exception. // This is because enable_shared_from_this::weak_ptr is NOT reconstructed - It is zero. #include #include #include #include #include #include #include #include "test_tools.hpp" #include namespace boost { namespace serialization { struct enable_shared_from_this_helper { std::set > m_esfth; void record(boost::shared_ptr sp){ m_esfth.insert(sp); } }; template void serialize( Archive & ar, boost::enable_shared_from_this & t, const unsigned int file_version ){ enable_shared_from_this_helper & h = ar.template get_helper< enable_shared_from_this_helper >(); shared_ptr sp = t.shared_from_this(); h.record(sp); } } // serialization } // boost class Base { friend class boost::serialization::access; template void serialize(Archive & ar, const unsigned int version) { ar & BOOST_SERIALIZATION_NVP(m_base); } protected: Base() {} virtual ~Base() {} // "virtual" forces RTTI, to enable serialization of Derived from Base pointer public: int m_base; }; class Derived : public Base, public boost::enable_shared_from_this { friend class boost::serialization::access; template void serialize(Archive & ar, const unsigned int version) { ar & BOOST_SERIALIZATION_BASE_OBJECT_NVP(Base); ar & BOOST_SERIALIZATION_BASE_OBJECT_NVP( boost::enable_shared_from_this ); ar & BOOST_SERIALIZATION_NVP(m_derived); } public: boost::shared_ptr SharedPtr() { return shared_from_this(); } int m_derived; Derived() {} ~Derived() {} }; // The following is required to enable serialization from Base pointer BOOST_CLASS_EXPORT(Derived) // This test passes void test_passes(){ std::stringstream ss; { boost::shared_ptr d(new Derived()); d->m_base = 1; d->m_derived = 2; // Get a raw pointer to Derived Derived* raw_d = d.get(); // Verify base and derived members BOOST_CHECK(raw_d->m_base==1); BOOST_CHECK(raw_d->m_derived==2); // verify shared_from_this BOOST_CHECK(d == raw_d->SharedPtr()); boost::archive::text_oarchive oa(ss); oa & BOOST_SERIALIZATION_NVP(d); } { // Deserialize it back into a vector of shared_ptr boost::shared_ptr d; ss.seekg(0); boost::archive::text_iarchive ia(ss); ia & BOOST_SERIALIZATION_NVP(d); // Get a raw pointer to Derived Derived* raw_d = d.get(); // Verify base and derived members BOOST_CHECK(raw_d->m_base==1); BOOST_CHECK(raw_d->m_derived==2); // verify shared_from_this BOOST_CHECK(d == raw_d->SharedPtr()); } } // This test fails void test_fails(){ std::stringstream ss; { boost::shared_ptr b(new Derived()); Derived* raw_d1 = static_cast(b.get()); raw_d1->m_base = 1; raw_d1->m_derived = 2; // Get a raw pointer to Derived via shared_ptr Derived* raw_d = static_cast(b.get()); // Verify base and derived members BOOST_CHECK(raw_d->m_base==1); BOOST_CHECK(raw_d->m_derived==2); // verify shared_from_this boost::shared_ptr d = raw_d->SharedPtr(); BOOST_CHECK(d == b); // Serialize the vector boost::archive::text_oarchive oa(ss); oa & BOOST_SERIALIZATION_NVP(b); } { // Deserialize it back into a vector of shared_ptr ss.seekg(0); boost::archive::text_iarchive ia(ss); boost::shared_ptr b; ia & BOOST_SERIALIZATION_NVP(b); // Get a raw pointer to Derived via shared_ptr Derived* raw_d = static_cast(b.get()); // Verify base and derived members BOOST_CHECK(raw_d->m_base==1); BOOST_CHECK(raw_d->m_derived==2); // verify shared_from_this // FAIL: The following line throws bad_weak_ptr exception boost::shared_ptr d = raw_d->SharedPtr(); BOOST_CHECK(d == b); } } int test_main(int /*argc*/, char * /*argv */[]){ test_fails(); test_passes(); return EXIT_SUCCESS; } // EOF