Vector of pointers. BOOST serialization

2.6k Views Asked by At

I want to serialize/deserialize using BOOST the values (not the pointers) of objects in the following vector:

std :: vector <A*> m_vector; 

To serialize I use the following code:

int nItems = m_vector.size();
ar & nItems;
std::for_each(m_vector.begin(), m_vector.end(), [&ar](A* pItem) {
    ar & *pItem;
});

And to deserialize:

int nItems;
ar & nItems;
for (int i = 0; i < nItems; ++i) {
    A* pItem;
    ar & *pItem;  ///////////// Run-Time Check Failure #3
    m_vector.push_back(pItem);
}

But when I run the program I get the following error:

Run-Time Check Failure # 3 - The variable 'pItem' is Being Used without Being initialized. 

What am I doing wrong?

Thank you.

2

There are 2 best solutions below

0
On

You will need to allocate memory for the object pointed to by pItem:

A* pItem = new A;
ar & *pItem;
m_vector.push_back(pItem);

The error was because although you had a pointer, there was no object at the memory location where the pointer pointed to -- the value of the pointer was garbage (uninitialized pointer).

Don't forget to call delete when you no longer need the object pointed to by the pointer in the vector to preven memory leak. Better yet, use a smart pointer (e.g. boost::shared_ptr<>) to ensure the memory is deallocated when no longer accessible.

2
On

2 years later, but worth mentioning.

There's been a better solution to serialize a vector of pointers to objects or any other STL container (list, set etc.). In order to serialize a vector, add:

#include <boost/serialization/vector.hpp>

and then you need to implement serialize() method and friend your class with archieve. Everything is explained in this example (read all comments carefully, they're very important):

#include <fstream>
#include <iostream>
#include <vector>
#include <iostream>

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


class Abc{
    // In order to make Abc serializable
    // you need to friend this lass with serialization::access
    friend class boost::serialization::access;

    // and then add this method
    template<class Archive>
    void serialize(Archive & ar, const unsigned int version)
    {
        // choose what class fields do you want to serialize
        ar & a;
        ar & b;
        ar & c;
    }
public:
    int a;
    int b;
    int c;

    // don't forget about default constructor! It's necessary for serialization!
    Abc(){};
    Abc(int a, int b, int c): a(a), b(b), c(c){};
};

class GpsPosition
{
private:
    // as mentioned above...
    friend class boost::serialization::access;
    template<class Archive>
    void serialize(Archive & ar, const unsigned int version)
    {
        ar & degrees;
        ar & minutes;
        ar & seconds;
        ar & wektorIntow;
    }
    int degrees;
    int minutes;
    float seconds;
public:
    std::vector<Abc*> abcVector;
    GpsPosition(){};
    GpsPosition(int d, int m, float s): degrees(d), minutes(m), seconds(s)
    {
        // adding some objects to abcVector
        abcVector.push_back(new Abc(1, 2, 3));
        abcVector.push_back(new Abc(3, 2, 3));
        abcVector.push_back(new Abc(2, 2, 3));
        abcVector.push_back(new Abc(1, 2, 3));
    }
    int getDegrees(){ return this->degrees; }
    int getMinutes(){ return this->minutes; }
    float getSeconds(){ return this->seconds; }
};

int main(){

    // And now how to use it

    // Saving to file:
    std::ofstream fileHandler("filename");
    const GpsPosition position1(35, 59, 24.567f);
    {
        boost::archive::text_oarchive boostOutputArchieve(fileHandler);
        boostOutputArchieve << position1;
    }

    // Reading from file:
    GpsPosition newPosition;
    {
        std::ifstream fileHandler;
        try{
            fileHandler.open("filenacme");
            boost::archive::text_iarchive boostInputArchieve(fileHandler);
            // read class state from archive
            boostInputArchieve >> newPosition;
            // archive and stream closed when destructors are called
            fileHandler.close();
            }
        catch (std::ifstream::failure e) {
            std::cerr << "Exception opening/reading/closing file";
        }
        catch(boost::archive::archive_exception e){
            std::cerr << "Exception opening/reading/closing file";
        }
    }

    // print to the console
    std::cout << newPosition.getMinutes() << std::endl; 
    std::cout << newPosition.abcVector[0]->a;
    std::cin.get();

    return 0;
}

For more information, check out this tutorial: http://www.boost.org/doc/libs/1_55_0/libs/serialization/doc/index.html