Hello everyone. I tried to compile a code that has written below and I
had met runtime error. That error is the memory corruption.
A memory corruption occurs when just before exit main function and
causes are in binary-serialization, but I don't understand this
fenomenon. If someone who knows the reason of this matter, please tell me.
[environment]
Windows XP 64bit
Visual Studio 2005 sp1
boost-1_34_1
#define _SCL_SECURE_NO_WARNINGS
#pragma warning(push)
#pragma warning(disable: 4267)
#pragma warning(disable: 4103)
#include <stdio.h>
#include <tchar.h>
#define CRTDBG_MAP_ALLOC
#include <stdlib.h>
#include <crtdbg.h>
#include <iostream>
#include <fstream>
#include <cstdlib>
#include <vector>
#include <boost/shared_ptr.hpp>
#include <boost/weak_ptr.hpp>
#include <boost/enable_shared_from_this.hpp>
#include <boost/serialization/serialization.hpp>
#include <boost/serialization/string.hpp>
#include <boost/serialization/vector.hpp>
#include <boost/serialization/shared_ptr.hpp>
#include <boost/serialization/weak_ptr.hpp>
#include <boost/serialization/version.hpp>
#include <boost/serialization/base_object.hpp>
#include <boost/serialization/tracking.hpp>
#include <boost/serialization/is_abstract.hpp>
#include <boost/serialization/nvp.hpp>
#include <boost/serialization/binary_object.hpp>
#include <boost/serialization/split_member.hpp>
#define BOOST_LIB_NAME boost_serialization
#include <boost/config/auto_link.hpp>
#include <boost/archive/binary_iarchive.hpp>
#include <boost/archive/binary_oarchive.hpp>
#include <boost/serialization/export.hpp>
#pragma warning(pop)
using namespace std;
using namespace boost;
using namespace boost::serialization;
using namespace boost::archive;
namespace test
{
class nodebase : public enable_shared_from_this<nodebase> { // occurs
memory corruption when serializing
public:
typedef shared_ptr<nodebase> NodePointer;
typedef weak_ptr<nodebase> NodeWeakPointer;
typedef vector<NodePointer> Children;
typedef Children::iterator ChildIterator;
typedef vector<NodeWeakPointer> Parents;
typedef Parents::iterator ParentIterator;
public:
nodebase();
nodebase(
const string &n );
nodebase(
const string &n, const Children &c );
nodebase(
const string &n,
const Children &c,
const Parents &p );
virtual ~nodebase();
private:
struct Impl {
Impl();
Impl( const string &n );
Impl( const string &n, const Children &v );
Impl( const string &n, const Children &v, const Parents &p );
public:
string name;
Children children;
Parents parents;
private:
friend class serialization::access;
template <class Archive>
void serialize( Archive &ar, const unsigned int version );
};
shared_ptr<Impl> pimpl;
private: // serialization
friend class serialization::access;
template <class Archive>
void serialize( Archive &ar, const unsigned int version );
public:
string getname( void ){ return pimpl->name; }
void SetParent( const NodePointer &parent );
void SetParents( const Parents &parents );
NodePointer GetParent( const string &name );
Parents GetParents( void );
Children GetChildren( void );
void AddChild( const NodePointer &child );
void RemoveChild( const NodePointer &child );
void Traverse( void );
private:
void Traverse( const NodePointer &root );
};
nodebase::Impl::Impl() {
}
nodebase::Impl::Impl( const string &n )
: name(n) {
}
nodebase::Impl::Impl( const string &n, const Children &c )
: name(n), children(c) {
}
nodebase::Impl::Impl( const string &n, const Children &c, const Parents &p )
: name(n), children(c), parents(p) {
}
template <class Archive>
void nodebase::Impl::serialize( Archive &ar, const unsigned int version ) {
ar & make_nvp( "name", make_binary_object( &name, sizeof(name) ) );
ar & make_nvp( "children", make_binary_object( &children,
sizeof(children) ) );
ar & make_nvp( "parents", make_binary_object( &parents, sizeof(parents) ) );
}
nodebase::nodebase() {
}
nodebase::nodebase( const string &n )
: pimpl( new Impl( n ) ) {
}
nodebase::nodebase( const string &n, const Children &c )
: pimpl( new Impl( n, c ) ) {
}
nodebase::nodebase( const string &n, const Children &c, const Parents &p )
: pimpl( new Impl( n, c, p ) ) {
}
nodebase::~nodebase() {
}
template <class Archive>
void nodebase::serialize( Archive &ar, const unsigned int version ) {
ar & make_nvp( "pimpl", make_binary_object( &pimpl, sizeof(pimpl) ) );
}
template void nodebase::serialize<archive::binary_oarchive>(
archive::binary_oarchive &ar,
const unsigned int version );
template void nodebase::serialize<archive::binary_iarchive>(
archive::binary_iarchive &ar,
const unsigned int version );
void nodebase::SetParent( const nodebase::NodePointer &p ) {
assert( pimpl->parents.size()+1 < 2 );
pimpl->parents.push_back( p );
}
nodebase::NodePointer nodebase::GetParent( const string &name ) {
for( ParentIterator i = pimpl->parents.begin(); i !=
pimpl->parents.end(); i++ ){
NodePointer tmp((*i));
if( tmp->getname() == name ) {
return tmp;
}
}
return NodePointer();
}
nodebase::Parents nodebase::GetParents( void ) {
return pimpl->parents;
}
nodebase::Children nodebase::GetChildren( void ) {
return pimpl->children;
}
void nodebase::AddChild( const nodebase::NodePointer &child ) {
child->SetParent( shared_from_this() ); //!!!!ERROR!!!! incur a memory leak
this->pimpl->children.push_back( child );
}
void nodebase::RemoveChild( const NodePointer &child ) {
for( ChildIterator i = pimpl->children.begin(); i !=
pimpl->children.end(); i++ ){
if( (*i).get() == child.get() ){
pimpl->children.erase( i );
break;
}
}
}
void nodebase::Traverse( void ) {
Children children = this->GetChildren();
for( ChildIterator i = children.begin(); i != children.end(); i++ ){
Traverse( *i );
}
}
void nodebase::Traverse( const NodePointer &node ) {
if( !node ){
return;
}
Children children = node->GetChildren();
for( ChildIterator i = children.begin(); i != children.end(); i++ ) {
Traverse( *i );
}
}
class simple_class { // not occur memory corruption when serializing
friend class access;
string name;
template <class Archive> void serialize( Archive &ar, unsigned int ) {
ar & name;
}
};
};
BOOST_CLASS_TRACKING(test::nodebase, boost::serialization::track_always);
int _tmain(int argc, _TCHAR* argv[])
{
using namespace test; {
shared_ptr<nodebase> root( new nodebase(string("root")) );
shared_ptr<nodebase> c1( new nodebase(string("c1")) );
shared_ptr<nodebase> c2( new nodebase(string("c2")) );
shared_ptr<nodebase> c3( new nodebase(string("c3")) );
shared_ptr<nodebase> c4( new nodebase(string("c4")) );
shared_ptr<nodebase> c5( new nodebase(string("c5")) );
c3->AddChild( c5 );
c1->AddChild( c3 );
c2->AddChild( c4 );
root->AddChild( c1 );
root->AddChild( c2 );
root->Traverse();
{ // output
ofstream ofile( "serialized", ios::binary );
try {
boost::archive::binary_oarchive oa( ofile );
oa << BOOST_SERIALIZATION_NVP(root);
} catch( boost::archive::archive_exception &e ) {
cout << "At the output : " << e.what() << endl;
ofile.close();
getchar();
exit(1);
}
ofile.close();
}
shared_ptr<nodebase> in; { // input
ifstream ifile( "serialized", ios::binary );
try {
boost::archive::binary_iarchive ia( ifile );
ia >> BOOST_SERIALIZATION_NVP(in);
in->Traverse();
} catch( boost::archive::archive_exception &e ) {
cout << "At the input : " << e.what() << endl;
ifile.close();
getchar();
exit(e.code);
}
ifile.close();
}
}
getchar();
return 0;
}