Boost logo

Boost Users :

Subject: [Boost-users] Boost serialisation: base ptr regression in 1.42
From: Avi Bahra (avibahra_at_[hidden])
Date: 2010-03-27 17:24:24


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



Boost-users list run by williamkempf at hotmail.com, kalb at libertysoft.com, bjorn.karlsson at readsoft.com, gregod at cs.rpi.edu, wekempf at cox.net