Boost logo

Boost Users :

Subject: [Boost-users] serialization 1.42 problems with enable_shared_from_this ?
From: Avi Bahra (avibahra_at_[hidden])
Date: 2010-04-05 12:05:53


Not quite sure what is going on here. I am
serializing shared_ptr, that make use of
derivation from enable_shared_from_this.

However when my class is restored from
disk, it appears that accessing shared_from_this()
throws a tr1::bad_weak_ptr.
Using boost 1.42, gcc 4.2.1, on suse linux.

Has any one hit a similar issues, or found any
work arounds ? Any help greatly appreciated.

Here is some contrived standalone code, that demonstrate
the problem.

/////////1/////////2/////////3/////////4/////////5/////////6/////////7/////////8
// =========== file Main.cpp ===================
// After restoring a class via shared_ptr it
// appears as if enable_shared_from_this has not
// been honoured. When accessing shared_from_this()
// I get tr1::bad_weak_ptr exception.

#include <iostream>
#include <fstream>
#include <assert.h>

#include <boost/archive/text_iarchive.hpp>
#include <boost/archive/text_oarchive.hpp>
#include <boost/serialization/base_object.hpp>
#include <boost/serialization/string.hpp>
#include <boost/serialization/vector.hpp>
#include <boost/serialization/shared_ptr.hpp>
#include <boost/serialization/export.hpp>

#include <boost/shared_ptr.hpp>
#include <boost/enable_shared_from_this.hpp>

using namespace std;
using namespace boost;

class Base :
    public boost::enable_shared_from_this<Base> ,
    private boost::noncopyable {
protected:
     Base() {}
    virtual ~Base() {}
public:
      virtual const std::string& name() const = 0;
private:
    friend class boost::serialization::access;
    template<class Archive>
    void serialize(Archive & ar, const unsigned int){}
};
typedef boost::shared_ptr<Base> base_ptr;

class Derived : public Base {
public:
    Derived(const std::string& name )
               : Base(), name_(name){}
    Derived() {}
    virtual ~Derived() {}

    virtual const std::string& name() const { return name_;}

    base_ptr find(const std::string& name) const {
        if (name_ == name) {
            Derived* nonConstThis = const_cast<Derived*>(this);
            return nonConstThis->shared_from_this(); // throws after restore
?
        }
        return base_ptr();
    }

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_;
    }
};
typedef boost::shared_ptr<Derived> d_ptr;

class Holder {
public:
    Holder() {}
    void add(d_ptr b) { vec_.push_back(b);}

    base_ptr find(const std::string& name) const {
        for(size_t i=0; i < vec_.size(); i++){
            base_ptr base = vec_[i]->find(name);
            if (base) return base;
        }
        return base_ptr();
    }
private:
    std::vector<d_ptr> vec_;

    friend class boost::serialization::access;
    template<class Archive>
    void serialize(Archive & ar, const unsigned int){
         ar & vec_;
    }
};

void save(const Holder& holder, const char* filename)
{
    std::ofstream ofs( filename );
    boost::archive::text_oarchive oa( ofs );
    oa << holder;
}

void restore(Holder& holder, const char* filename)
{
    std::ifstream ifs( filename );
    boost::archive::text_iarchive ia( ifs );
    ia >> holder;
}

int main()
{
    std::string fileName = "test.txt";

    {
        Holder holder;
        holder.add( d_ptr(new Derived("me")));
        holder.add( d_ptr(new Derived("you")));

        base_ptr b = holder.find("me");
        assert(b.get()); // works

        save(holder, fileName.c_str());
    }

    Holder restored;
    restore(restored,fileName.c_str());

    // why does the restored class throw
    // a weak ptr exception
    try {
        base_ptr b = restored.find("me"); // fails ?
        assert(b.get()); // never gets here
    }
    catch (std::exception& e) {
        std::cout << "Ooops exception " << e.what()
        << " thrown, test failed??? \n";
        std::remove(fileName.c_str());
        return 1;
    }

    std::remove(fileName.c_str());
    cout << "test passed\n";
}

  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