I have a serious regression in boost 1.42 serialisation. Now getting a unregistered class, exception, on Suse linux using gcc 4.2.1. This test passes on boost 1.39/1.40. There are 3 files involved to recreate the crash: included below: Main.cpp BaseHolder.hpp BaseHolder.cpp The file BaseHolder.hpp/cpp defines 3 classes Base Derived BaseHolder Here is what I found: 1/ If all the functionality is put in one file. i.e Main.cpp then _no_ crash 2/ If all 3 files are compiled together then _no_ crash 3/ However if BaseHolder is added to static library and linked with Main.cpp then we get the _crash_ ( only in 1.42 ) Also getting a spurious warning message: Again this warning only appears in 1.42 /var/tmp/ma0/boost/boost_1_42_0/boost/mpl/print.hpp: In instantiation of ?boost::mpl::print<boost::serialization::BOOST_SERIALIZATION_STATIC_WARNING_LINE<98>
?: /var/tmp/ma0/boost/boost_1_42_0/boost/serialization/static_warning.hpp:92: instantiated from ?boost::serialization::static_warning_test<false, 98>? /var/tmp/ma0/boost/boost_1_42_0/boost/archive/detail/check.hpp:98: instantiated from ?void boost::archive::detail::check_object_tracking() [with T = Derived]? /var/tmp/ma0/boost/boost_1_42_0/boost/archive/detail/oserializer.hpp:313: instantiated from ?static void boost::archive::detail::save_non_pointer_type<Archive>::invoke(Archive&, T&) [with T = Derived, Archive = boost::archive::text_oarchive]? /var/tmp/ma0/boost/boost_1_42_0/boost/archive/detail/oserializer.hpp:525: instantiated from ?void boost::archive::save(Archive&, T&) [with Archive = boost::archive::text_oarchive, T = Derived]? /var/tmp/ma0/boost/boost_1_42_0/boost/archive/detail/common_oarchive.hpp:69: instantiated from ?void boost::archive::detail::common_oarchive<Archive>::save_override(T&, int) [with T = Derived, Archive = boost::archive::text_oarchive]? /var/tmp/ma0/boost/boost_1_42_0/boost/archive/basic_text_oarchive.hpp:80: instantiated from ?void boost::archive::basic_text_oarchive<Archive>::save_override(T&, int) [with T = Derived, Archive = boost::archive::text_oarchive]? /var/tmp/ma0/boost/boost_1_42_0/boost/archive/detail/interface_oarchive.hpp:64: instantiated from ?Archive& boost::archive::detail::interface_oarchive<Archive>::operator<<(T&) [with T = Derived, Archive = boost::archive::text_oarchive]? /var/tmp/ma0/clientRoot/workspace/MyProject/SCRATCH/src/Main.cpp:16: instantiated from here /var/tmp/ma0/boost/boost_1_42_0/boost/mpl/print.hpp:55: warning: comparison between signed and unsigned integer expressions gcc.archive bin/gcc-4.2.1/debug/link-static/libnodeattr.a gcc.link bin/gcc-4.2.1/debug/test
Here are the 3 files: // =========== file Main.cpp ============================ #include <iostream> #include <fstream> #include "BaseHolder.hpp" using namespace std; int main() { std::string fileName = "test.txt"; { // If this scope is commented out, crash goes away ??? Derived saved("varname"); { std::ofstream ofs( fileName.c_str() ); boost::archive::text_oarchive oa( ofs ); oa << saved; } Derived restored; { std::ifstream ifs( fileName.c_str() ); boost::archive::text_iarchive ia( ifs ); ia >> restored; } assert(saved == restored ); std::remove(fileName.c_str()); } { BaseHolder saved(Derived("varname")); { std::ofstream ofs( fileName.c_str() ); boost::archive::text_oarchive oa( ofs ); oa << saved; } BaseHolder restored; { std::ifstream ifs( fileName.c_str() ); boost::archive::text_iarchive ia( ifs ); ia >> restored; } assert(saved == restored); std::remove(fileName.c_str()); } cout << "Test passed \n"; } //=================== file BaseHolder.hpp ============= #ifndef BASEHOLDER_HPP_ #define BASEHOLDER_HPP_ // defines classes: // Base // Derived // BaseHolder #include <boost/archive/text_iarchive.hpp> #include <boost/archive/text_oarchive.hpp> #include <boost/serialization/base_object.hpp> #include <boost/serialization/serialization.hpp> #include <boost/serialization/vector.hpp> #include <boost/serialization/string.hpp> #include <boost/serialization/assume_abstract.hpp> class Base { public: Base(); virtual ~Base(); virtual bool compare(Base*) const = 0; virtual std::string name() const = 0; private: friend class boost::serialization::access; template<class Archive> void serialize(Archive &, const unsigned int){} }; class Derived : public Base { public: Derived(const std::string& n) : name_(n) {} Derived() {} bool operator==(const Derived& rhs) const; virtual std::string name() const { return name_;} virtual bool compare(Base*) const; private: std::string name_; friend class boost::serialization::access; template<class Archive> void serialize(Archive & ar, const unsigned int) { ar & boost::serialization::base_object<Base>(*this); ar & name_; } }; class BaseHolder { public: BaseHolder( const Derived& ); BaseHolder(); ~BaseHolder(); std::string name() const { return basePtr_->name();} bool operator==(const BaseHolder& rhs) const { return basePtr_->compare(rhs.basePtr_); } private: Base* basePtr_; friend class boost::serialization::access; template<class Archive> void serialize(Archive & ar, const unsigned){ ar & basePtr_; } }; #endif //============= File BaseHolder.cpp ========= // implements class: // Base // Derived // BaseHolder #include <assert.h> #include <sstream> #include <boost/serialization/export.hpp> #include "BaseHolder.hpp" using namespace std; // class Base Base::Base() {} Base::~Base() {} // class derived bool Derived::compare(Base* rb) const { Derived* rhs = dynamic_cast<Derived*>(rb); if(!rhs) return false; return operator==(*rhs); } bool Derived::operator==(const Derived& rhs) const { if (name_ != rhs.name_) { return false; } return true; } BOOST_CLASS_EXPORT(Derived); // class BaseHolder BaseHolder::BaseHolder() : basePtr_(NULL) {} BaseHolder::BaseHolder( const Derived& r) : basePtr_(new Derived(r)) {} BaseHolder::~BaseHolder() { delete basePtr_;} Best regards, Ta, Avi