5

I am working on a simple serialization class. I keep throwing an exception on the input stream. I have put together the below example of what I am attempting to accomplish in simple terms.

I have this simple example of boost serialization that I am getting an exception on:

#include <boost/serialization/serialization.hpp> 
#include <boost/archive/text_oarchive.hpp> 
#include <boost/archive/text_iarchive.hpp> 
#include <boost/serialization/export.hpp> 
#define NVP(X) X 

class base { 
public: 
friend class boost::serialization::access; 
base (){ v1 = 10;} 
int v1; 
template<class Archive> 
void serialize(Archive & ar, const unsigned int file_version) 
{ 

    ar & NVP(v1); 
} 
virtual void bla()=0; 
}; 


class derived : public base { 
public: 
friend class boost::serialization::access; 
int v2 ; 
derived() { v2 = 100;} 
template<class Archive> 
void serialize(Archive & ar, const unsigned int file_version){ 
    boost::serialization::base_object<base>(* this); 
    ar & NVP(v2); 
} 

virtual void bla(){};
};
BOOST_CLASS_EXPORT(base);
BOOST_CLASS_EXPORT_GUID(derived, "derived");

int main ( )
{
std::stringstream ss;
boost::archive::text_oarchive ar(ss);
base *b = new derived();
ar << NVP(b);
std::cout << ss.str()<<std::endl;



std::istringstream ssi;
base *b1 = new derived();
{
boost::archive::text_iarchive ar1(ssi);
ar1 >> b1;
}
//std::cout << ssi.str();
std::cout << "v1: " << b1->v1 << std::endl;

}

The exception that I am getting is:

terminate called after throwing an instance of 'boost::archive::archive_exception'
  what():  input stream error

Any help would be appreciated.

1 Answer 1

4

You're reading from an empty stream:

std::istringstream ssi;
// ...
boost::archive::text_iarchive ar1(ssi);

Also, you leak this object:

base *b1 = new derived();

Here's a fixed example, notes:

  • it's very good practice/important to close archives before using the streamed data
  • BOOST_CLASS_EXPORT_GUID(derived, "derived") doesn't add anything beyond BOOST_CLASS_EXPORT(derived)
  • you can print the v2 conditionally:

    if (auto* d = dynamic_cast<derived*>(b1))
        std::cout << "v2: " << d->v2 << std::endl;
    
  • I've used bla() as an example to print the values instead

  • NVP() is a bit iffy there. Why not just leave it out for non-tagged archives (ie. other than XML)? If you intend to support XML, just use BOOST_SERIALIZATION_NVP, boost::serialization::make_nvp etc.

  • std::cout << "v2: " << b1->v2 << std::endl; was completely out of place

  • just initialize b1 to null so you don't leak it; remember to free all pointers (use smart pointers!)

  • the mix of public: and friend in your types didn't really mean much

Live On Coliru

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

class base {
  public:
    base(int v1) : v1(v1) {}
    virtual void bla() const = 0;

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

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

class derived : public base {
  public:
    derived(int v1 = 10, int v2 = 100) : base(v1), v2(v2) {}
    virtual void bla() const {
        std::cout << "v1: " << v1 << ", v2: " << v2 << "\n";
    }

  private:
    friend class boost::serialization::access;
    int v2;
    template <class Archive> void serialize(Archive &ar, unsigned /*int const file_version*/) {
        boost::serialization::base_object<base>(*this);
        ar & BOOST_SERIALIZATION_NVP(v2);
    }
};

BOOST_CLASS_EXPORT(base)
BOOST_CLASS_EXPORT(derived)

int main() {
    std::stringstream ss;
    {
        boost::archive::text_oarchive ar(ss);
        base *b = new derived();
        ar << boost::serialization::make_nvp("base", b);

        delete b; // TODO use RAII instead
    }

    std::cout << ss.str() << std::endl;
    base *deserialized = nullptr;
    {
        boost::archive::text_iarchive ar1(ss);
        ar1 >> boost::serialization::make_nvp("base", deserialized);
    }

    deserialized->bla();
    delete deserialized;
}

Prints

22 serialization::archive 12 0 7 derived 1 0
0 100

v1: 10, v2: 100
Sign up to request clarification or add additional context in comments.

3 Comments

Thank you sir. This is a case of following the example a bit too close. Now i see that my stream literally has nothing in it to deserialize.
I just realized I didn't warn about delete-ing deserialized anyways. So, add that to the list :)
thanks sehe. I will have another one for you here in a bit. I am still getting input stream error exception in my actual project. I am working on simplifying the problem now.

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.