Boost logo

Boost Users :

From: Bill Lear (rael_at_[hidden])
Date: 2005-01-02 14:46:48


I have spent several hours combing the documentation and archives, but
can't seem to find an answer to my problem.

I have an abstract base class, Operation with a pure virtual function
'double value() = 0'. I derive a class, BinaryOperation from
Operation. It takes as arguments an operation type (+, -, *, /) and
two Operation pointers --- one for the left operand, one for the
right. It stores these two pointers internally and uses them when the
value() method is invoked.

I derive two more classes from Operation, trivial, made-up, useless
ones. One is called IncrementOperation, one is called
DecrementOperation.

I can save to an XML archive properly, but when I try to restore, it
core dumps. I am running gcc-3.2. I have tried everything I can
think of, but am stuck. I have tried using polymorphic_xml_iarchive
(and corresponding output version), but it still fails.

The first few stack frames from GDB are:

#0 0x0808897f in ?? ()
#1 0x08052f7d in boost::archive::detail::basic_iarchive::load_pointer(void*&, boost::archive::detail::basic_pointer_iserializer const*, boost::archive::detail::basic_pointer_iserializer const* (*)(boost::serialization::extended_type_info const&)) ()
#2 0x0804c78a in boost::archive::detail::load_pointer_type<boost::archive::xml_iarchive, Operation*>::invoke(boost::archive::xml_iarchive&, Operation*&) (
    ar=@0xbffff0e0, t=@0xbffff330)
    at /usr/local/include/boost-1_32/boost/archive/detail/iserializer.hpp:450
#3 0x0804c51a in load<boost::archive::xml_iarchive, Operation*> (
    ar=@0xbffff0e0, t=@0xbffff330)
    at /usr/local/include/boost-1_32/boost/archive/detail/iserializer.hpp:529

Following my sig, I've posted the xml input file that is generated by
the save, and then following that, the C++ code (fairly short). It is
failing on the following line:

    ia & BOOST_SERIALIZATION_NVP(t);

Any help would be appreciated.

Thanks.

Bill

<?xml version="1.0" encoding="UTF-8" standalone="yes" ?>
<!DOCTYPE boost_serialization>
<boost_serialization signature="serialization::archive" version="3">
<t class_id="1" class_name="BinaryOperation" tracking_level="1" version="0" object_id="_0">
        <Operation class_id="0" tracking_level="1" version="0" object_id="_1"></Operation>
        <_op>42</_op>
        <_left_operand class_id_reference="1" object_id="_2">
                <Operation object_id="_3"></Operation>
                <_op>43</_op>
                <_left_operand class_id="2" class_name="IncrementOperation" tracking_level="1" version="0" object_id="_4">
                        <Operation object_id="_5"></Operation>
                        <_init>33</_init>
                </_left_operand>
                <_right_operand class_id="3" class_name="DecrementOperation" tracking_level="1" version="0" object_id="_6">
                        <Operation object_id="_7"></Operation>
                        <_init>333</_init>
                </_right_operand>
        </_left_operand>
        <_right_operand class_id_reference="1" object_id="_8">
                <Operation object_id="_9"></Operation>
                <_op>45</_op>
                <_left_operand class_id_reference="3" object_id="_10">
                        <Operation object_id="_11"></Operation>
                        <_init>444</_init>
                </_left_operand>
                <_right_operand class_id_reference="2" object_id="_12">
                        <Operation object_id="_13"></Operation>
                        <_init>44</_init>
                </_right_operand>
        </_right_operand>
</t>
</boost_serialization>

#include <string>
#include <iomanip>
#include <iostream>
#include <fstream>
#include <stdexcept>

#include <boost/serialization/nvp.hpp>

#include <boost/archive/xml_iarchive.hpp>
#include <boost/archive/xml_oarchive.hpp>
//#include <boost/archive/polymorphic_xml_iarchive.hpp>
//#include <boost/archive/polymorphic_xml_oarchive.hpp>

#include <boost/serialization/export.hpp>

class Operation {
public:
    Operation() { }
    virtual ~Operation() { }
    virtual double value() = 0;

private:
    friend class boost::serialization::access;

    template<class Archive>
    void serialize(Archive & ar, const unsigned int /* file_version */){
    }
};

BOOST_IS_ABSTRACT(Operation);

class BinaryOperation: public Operation {
public:
    BinaryOperation() : _op(' '), _left_operand(0), _right_operand(0) { }

    BinaryOperation(char op, Operation* left_operand, Operation* right_operand)
        : _op(op), _left_operand(left_operand), _right_operand(right_operand) {
    }

    virtual ~BinaryOperation() { }

    virtual double value() {
        switch (_op) {
            case '+':
                return _left_operand->value() + _right_operand->value(); break;
            case '-':
                return _left_operand->value() - _right_operand->value(); break;
            case '*':
                return _left_operand->value() * _right_operand->value(); break;
            case '/':
                return _left_operand->value() / _right_operand->value(); break;
        }
    }

protected:
    char _op;
    Operation* _left_operand;
    Operation* _right_operand;

    friend class boost::serialization::access;

    template<class Archive>
    void serialize(Archive & ar, const unsigned int /* file_version */){
        ar & BOOST_SERIALIZATION_BASE_OBJECT_NVP(Operation)
            & BOOST_SERIALIZATION_NVP(_op)
            & BOOST_SERIALIZATION_NVP(_left_operand)
            & BOOST_SERIALIZATION_NVP(_right_operand);
    }
};

BOOST_CLASS_EXPORT_GUID(BinaryOperation, "BinaryOperation");

class IncrementOperation : public Operation {
public:
    IncrementOperation() : _init(0) {
    }

    IncrementOperation(double init) : _init(init) {
    }

    virtual double value() {
        return _init++;
    }
protected:
    double _init;

    friend class boost::serialization::access;

    template<class Archive>
    void serialize(Archive & ar, const unsigned int /* file_version */){
        ar & BOOST_SERIALIZATION_BASE_OBJECT_NVP(Operation)
            & BOOST_SERIALIZATION_NVP(_init);
    }
};

BOOST_CLASS_EXPORT_GUID(IncrementOperation, "IncrementOperation");

class DecrementOperation : public Operation {
public:
    DecrementOperation() : _init(0) {
    }

    DecrementOperation(double init) : _init(init) {
    }

    virtual double value() {
        return _init--;
    }
protected:
    double _init;

    friend class boost::serialization::access;

    template<class Archive>
    void serialize(Archive & ar, const unsigned int /* file_version */){
        ar & BOOST_SERIALIZATION_BASE_OBJECT_NVP(Operation)
            & BOOST_SERIALIZATION_NVP(_init);
    }
};

BOOST_CLASS_EXPORT_GUID(DecrementOperation, "DecrementOperation");

void save_Operation(const Operation* t) {
    std::ofstream ofs("operation.xml");
    assert(ofs.good());
    boost::archive::xml_oarchive oa(ofs);
    //boost::archive::polymorphic_xml_oarchive oa(ofs);

    oa & BOOST_SERIALIZATION_NVP(t);
}

void restore_Operation(Operation*& t) {
    std::ifstream ifs("operation.xml");
    if (!ifs.good()) {
        throw std::runtime_error("No input archive file");
    }
    boost::archive::xml_iarchive ia(ifs);
    //boost::archive::polymorphic_xml_iarchive ia(ifs);

    std::cout << "Reading ...\n";
    ia & BOOST_SERIALIZATION_NVP(t);
    std::cout << "Done reading ...\n";
}

int main(int, char *[]) {
    try {
        Operation* a = new BinaryOperation('+',
                                     new IncrementOperation(33),
                                     new DecrementOperation(333));
        Operation* b = new BinaryOperation('-',
                                     new DecrementOperation(444),
                                     new IncrementOperation(44));
        Operation* c = new BinaryOperation('*', a, b);

        save_Operation(c);

        Operation* new_c;

        std::cout << "Restoring\n";

        restore_Operation(new_c);
    } catch (std::exception e) {
        std::cerr << e.what() << '\n';
        return 1;
    }

    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