Hans Hohenfeld
Hans Hohenfeld

Reputation: 1739

boost serialization / Deserialization of std::vector<float> member fails

Good afternoon,

I'm playing around with boost::serialization for the first time and am currently failing with some very basic task. I stripped down my code to the very basic, first the class defininiton for a simple class with just one std::vector member:

#ifndef DATA_H
#define DATA_H

#include <string>
#include <vector>

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

namespace ml {
    class Data {
        private:
            std::vector<float> d;

            friend class boost::serialization::access;

            template<class Archive>
            void serialize(Archive& ar, const unsigned int version);
        public:

            static Data Load(const std::string& filename);

            Data(const std::vector<float>& d);

            Data(const Data& rhs);
            Data();

            ~Data();

            Data& operator=(const Data& rhs);

            void save(const std::string& filename);

            std::vector<float> getD() const;
    };
}
#endif // DATA_H 

The implementation:

#include <iostream>
#include <fstream>

#include <boost/serialization/vector.hpp>

#include "Data.h"

ml::Data::Data(const std::vector<float>& d) : d(d)
{
}

ml::Data::Data(const Data& rhs)
{
    d = rhs.d;
}

ml::Data::Data()
{

}

ml::Data& ml::Data::operator=(const Data& rhs)
{
    d = rhs.d;

    return *this;
}

ml::Data ml::Data::Load(const std::string& filename)
{
    Data data;

    std::ifstream file(filename.c_str());

    boost::archive::text_iarchive ia(file);

    ia >> data;

    return data;
}

ml::Data::~Data()
{
}

void ml::Data::save(const std::string& filename)
{
    std::ofstream file(filename.c_str());    

    boost::archive::text_oarchive oa(file);

    oa << this;
}

std::vector<float> ml::Data::getD() const
{
   return d;
}

template<class Archive>
void ml::Data::serialize(Archive& ar, const unsigned int version)
{
   ar & d;

   std::cout << "Debug: " << d.size() << std::endl;
}

And a very small main program:

#include <iostream>

#include "Data.h"

int main(int argc, char** argv)
{
    const std::string filename("./test.txt");
    const int limit = 100;

    std::vector<float> orig;
    std::vector<float> copy;

    for(int i=0; i<limit; ++i) {
        orig.push_back(i);
    }

    ml::Data origData(orig);
    origData.save(filename);

    ml::Data copyData = ml::Data::Load(filename);

    orig = origData.getD();
    copy = copyData.getD();

    std::cout << "Sizes: "    << std::endl;
    std::cout << "Original: " << orig.size() << std::endl;
    std::cout << "Copy: "     << copy.size() << std::endl;

    return 0;
}

The program output is:

Debug: 100 
Debug: 0 
Sizes:  
Original: 100 
Copy: 0

Serialization and file output seem to work, the resulting file looks as expected, but de-serialization seems to fail. There is no further error output or any hint, what goes wrong. Boost version is 1.60.0 if that is of interest.

So, any idea what is going wrong?

Thank you in advance.

Upvotes: 0

Views: 982

Answers (1)

sehe
sehe

Reputation: 393934

Your serialization serializes a pointer:

oa << this;

The deserialization deserializes into a reference:

Data data;
ia >> data;

That's a bug. The result is undefined. Fix it:

oa << *this;

Demo

Live On Coliru

Prints:

Debug (loading: false) 5
Original: 5
Debug (loading: true) 5
Copy: 5

Code:

#ifndef DATA_H
#define DATA_H

#include <string>
#include <vector>

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

namespace ml {
    class Data {
        private:
            std::vector<float> d;

            friend class boost::serialization::access;

            template<class Archive>
            void serialize(Archive& ar, const unsigned int version);
        public:

            static Data Load(const std::string& filename);

            Data(const std::vector<float>& d) : d(d) {}
            //Data(const Data& rhs) = default;
            Data() = default;
            //~Data() = default;
            //Data& operator=(const Data& rhs) = default;

            void save(const std::string& filename);

            std::vector<float> getD() const;
    };
}
#endif // DATA_H 

#include <iostream>
#include <fstream>

#include <boost/serialization/vector.hpp>

//#include "Data.h"
ml::Data ml::Data::Load(const std::string& filename)
{
    Data data;

    std::ifstream file(filename.c_str());

    boost::archive::text_iarchive ia(file);

    ia >> data;

    return data;
}

void ml::Data::save(const std::string& filename)
{
    std::ofstream file(filename.c_str());    

    boost::archive::text_oarchive oa(file);

    oa << *this;
}

std::vector<float> ml::Data::getD() const
{
   return d;
}

template<class Archive>
void ml::Data::serialize(Archive& ar, const unsigned int /*version*/)
{
   ar & d;

   std::cout << "Debug (loading: " << std::boolalpha << typename Archive::is_loading::type() << ") " << d.size() << std::endl;
}

#include <iostream>

int main()
{
    const std::string filename("./test.txt");
    const int limit = 5;

    {
        std::vector<float> orig;

        for(int i=0; i<limit; ++i) { orig.push_back(i); }

        ml::Data origData(orig);
        origData.save(filename);

        orig = origData.getD();
        std::cout << "Original: " << orig.size() << std::endl;
    }

    ml::Data copyData = ml::Data::Load(filename);
    std::cout << "Copy: " << copyData.getD().size() << std::endl;
}

Upvotes: 2

Related Questions