Hi All,
Sorry for posting twice in two days, but I'm having lots of trouble getting this right.
Robert points out in the bus route example that the memory leaks can be solved using shared_ptrs (bottom of this page: http://www.boost.org/doc/libs/1_47_0/libs/serialization/doc/tutorial.html#examples)
I have a basic example (below), quite like the bus route, that has memory leaks when using raw pointers. I've converted it to shared_ptrs but the leaks are exactly the same. Where have I gone wrong?
I'm using VS2010 (hence the memory leak headers & function call to _CrtDumpMemoryLeaks();).
Any help much appreciated!
--------------------------------------------------------
Example that replicates problem:
#define _CRTDBG_MAP_ALLOC
#include <stdlib.h>
#include <crtdbg.h>
#include <boost/archive/xml_iarchive.hpp>
#include <boost/archive/xml_oarchive.hpp>
#include <boost/serialization/string.hpp>
#include <boost/serialization/vector.hpp>
#include <boost/serialization/export.hpp>
#include <boost/serialization/shared_ptr.hpp>
#include <boost/shared_ptr.hpp>
#include <boost/make_shared.hpp>
#include <iostream>
#include <fstream>
#include <string>
class Distribution
{
public:
Distribution(void) {};
~Distribution(void) {};
virtual std::string getType() = 0;
protected:
std::string m_Type;
private:
friend class boost::serialization::access;
template<class Archive>
void serialize(Archive& ar, const unsigned int version) {};
};
BOOST_SERIALIZATION_ASSUME_ABSTRACT(Distribution)
class ContinuousDist : public Distribution
{
public:
ContinuousDist()
{
m_Type = "Continuous";
m_Location = 80.0;
m_Scale = 5.0;
m_Shape = 0.0;
};
~ContinuousDist(void) {};
virtual std::string getType() {return m_Type;};
private:
double m_Location;
double m_Scale;
double m_Shape;
friend class boost::serialization::access;
template<class Archive>
void serialize(Archive& ar, const unsigned int version)
{
ar & BOOST_SERIALIZATION_BASE_OBJECT_NVP(Distribution)
& BOOST_SERIALIZATION_NVP(m_Type)
& BOOST_SERIALIZATION_NVP(m_Location)
& BOOST_SERIALIZATION_NVP(m_Scale)
& BOOST_SERIALIZATION_NVP(m_Shape);
};
};
BOOST_CLASS_EXPORT(ContinuousDist);
class DiscreteDist : public Distribution
{
public:
DiscreteDist(void)
{
m_Type = "Discrete";
m_Data.push_back(1.2);
m_Data.push_back(2.5);
m_PMF.push_back(0.8);
m_PMF.push_back(0.2);
};
~DiscreteDist(void){};
virtual std::string getType() {return m_Type;};
private:
std::vector<double> m_Data;
std::vector<double> m_PMF;
friend class boost::serialization::access;
template<class Archive>
void serialize(Archive& ar, const unsigned int version)
{
ar & BOOST_SERIALIZATION_BASE_OBJECT_NVP(Distribution)
& BOOST_SERIALIZATION_NVP(m_Type)
& BOOST_SERIALIZATION_NVP(m_Data)
& BOOST_SERIALIZATION_NVP(m_PMF);
};
};
BOOST_CLASS_EXPORT(DiscreteDist);
typedef boost::shared_ptr<Distribution> DistributionPtr;
class Parameter
{
public:
Parameter()
{
m_ID = 0;
};
Parameter(int id, int type)
{
m_ID = id;
if(type == 1)
m_pDist = boost::make_shared<DiscreteDist>();
else
m_pDist = boost::make_shared<ContinuousDist>();
};
~Parameter(void){};
DistributionPtr getDist() {return m_pDist;};
int getID() {return m_ID;};
private:
DistributionPtr m_pDist;
int m_ID;
friend class boost::serialization::access;
template<class Archive>
void serialize(Archive& ar, const unsigned int version)
{
ar & BOOST_SERIALIZATION_NVP(m_ID)
& BOOST_SERIALIZATION_NVP(m_pDist);
};
};
typedef boost::shared_ptr<Parameter> ParameterPtr;
void load(std::vector<ParameterPtr>& vP, std::string file)
{
std::ifstream ifs(file.c_str());
boost::archive::xml_iarchive ia(ifs);
ia >> BOOST_SERIALIZATION_NVP(vP);
}
void save(std::vector<ParameterPtr>& vP, std::string file)
{
std::ofstream ofs(file.c_str());
boost::archive::xml_oarchive oa(ofs);
oa << BOOST_SERIALIZATION_NVP(vP);
}
int main()
{
// tbe file to read/save from/to
std::string file = "archive.xml";
// make some Parmeters
std::vector<ParameterPtr> vParam;
vParam.push_back( boost::make_shared<Parameter>(1,1) );
vParam.push_back( boost::make_shared<Parameter>(2,2) );
// display for checking
for(unsigned int i = 0; i != vParam.size(); ++i)
std::cout << "P: " << vParam.at(i)->getDist()->getType() << std::endl;
// save the file
std::cout << "Writing..." << std::endl;
save(vParam,file);
// read the file
std::cout << "Reading..." << std::endl;
load(vParam,file);
// display for checking
for(unsigned int i = 0; i != vParam.size(); ++i)
std::cout << "P: " << vParam.at(i)->getDist()->getType() << std::endl;
std::cin.get(); // hold console window open
_CrtDumpMemoryLeaks(); // report memory leaks
}