Boost logo

Boost Users :

Subject: [Boost-users] [Serialization] Problem serializing directly and through base pointer in the same program.
From: Travis Abbott (typedef.struct_at_[hidden])
Date: 2010-09-20 19:55:44


Hi,
    I am using Boost.Serialization to serialize classes through a shared_ptr to
an abstract base class. Sometimes, I also serialize these classes directly. This
was working for me in version 1.40, but not versions 1.41 or 1.44.

    If I serialize only shared_ptr<BaseClass> instances, everything is fine.
If I link in code that serializes the derived class directly, even if that code
is never called, serialization of shared_ptr<BaseClass> instances throws an
exception ("unregistered class").

    A few notes about what I am doing:

I am calling BOOST_CLASS_EXPORT in the implementation file for each serializable
class.

I am using a template function for serialization that accepts any serializable
type, creates a new text_oarchiver on the stack, and returns a string. This is
called from many places in my application with many different types of things
(making it hard to have a central place to put all the BOOST_CLASS_EXPORTs).

    I am having this problem on RHEL5 with gcc 4.1.2 WITHOUT optimization turned
on. It works as expected with -O1 or higher. On WinXP with Visual Studio 2005,
it fails in both release and debug mode.

    The problem also seems to depend on the order that the object files get
written into the executable. If I include the file that is calling
BOOST_CLASS_EXPORT first, things work as expected, but fail otherwise.
(e.g., g++ obj.cpp main.cpp ... works, g++ main.cpp obj.cpp ... fails).

    Here are 3 source files, obj.h, obj.cpp, main.cpp that demonstrate this
problem. The line in main:

        fromString(toString(obj), obj2);

causes the code just before it (using shared_ptr) to fail. If anyone
can let me know
if I am misusing the library somehow, or if there is a cleaner way to accomplish
what I am trying to do, I would be very appreciative.

Thanks,
Travis Abbott

--------------------------8< obj.h 8< --------------------------
#pragma once

#include <boost/serialization/void_cast.hpp>

#include <string>

class Base
{
public:
    virtual ~Base() {}
    virtual std::string name() const = 0;
};

class Obj : public Base
{
public:
    std::string name() const { return "Obj"; }
    template<typename Arch>
    void serialize(Arch& arch, const unsigned version)
    {
        boost::serialization::void_cast_register<Obj, Base>(
            static_cast<Obj*>(NULL),
            static_cast<Base*>(NULL));
        arch & data;
    }

    int data;
};

--------------------------8< obj.cpp 8< --------------------------
#include "obj.h"

#include <boost/archive/text_oarchive.hpp>
#include <boost/archive/text_iarchive.hpp>
#include <boost/serialization/export.hpp>

BOOST_CLASS_EXPORT(Obj)

--------------------------8< main.cpp 8< --------------------------
#include "obj.h"

#include <boost/serialization/shared_ptr.hpp>
#include <boost/archive/text_iarchive.hpp>
#include <boost/archive/text_oarchive.hpp>
#include <boost/shared_ptr.hpp>
#include <iostream>
#include <sstream>
#include <stdexcept>
#include <string>

using boost::shared_ptr;
using namespace std;

template<typename T>
string toString(const T& obj)
{
    ostringstream ss;
    boost::archive::text_oarchive arch(ss);
    arch << obj;
    return ss.str();
}

template<typename T>
void fromString(const string& s, T& obj)
{
    istringstream ss(s);
    boost::archive::text_iarchive arch(ss);
    arch >> obj;
}

int main()
{
    try {
        shared_ptr<Base> pobj(new Obj), pobj2;
        fromString(toString(pobj), pobj2);
        cout << pobj2->name() << endl;

        // Compiling this causes runtime failure in code above.
        Obj obj, obj2;
        fromString(toString(obj), obj2);
        cout << obj2.name() << endl;
    } catch (const exception& e) {
        cerr << "Error: " << e.what() << endl;
    }

    return 0;
}


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