2016-03-05 94 views
0

你好我正在檢查C++中的各種對象序列化方法,但我找不到合適的解決方案。我正在檢查的一個正在使用宏來序列化各種類。代碼編譯,但我得到0xC0000005: Access violation reading location 0xCCCCCCC8.當功能serialize_example();正在呼叫Event* newEvent = dynamic_cast<Event*>(Persistent::load(stream));事件類序列化

Persistent * obj = dynamic_cast<Persistent *>(clone);調用發生異常。任何人都可以幫助我解決這個問題?下面是代碼:

void serialize_example() 
{ 
auto_ptr<Event> event(new Event()); 

fstream file("try.data", 
    ios::out | ios::in | ios::binary | ios::trunc); 

ArchiveFile stream(&file); 

if (!file) 
    throw "Unable to open file for writing"; 

event->store(stream); 

file.seekg(0, ios::beg); 

Event* newEvent = dynamic_cast<Event*>(Persistent::load(stream)); 

event.reset(newEvent); 

file.close(); 
} 

Event.h

#pragma once 
#include "Persist.h" 
#define PERSISTENT_DECL(className) \ 
public: \ 
virtual Clonable* createObj() \ 
{ \ 
return new className(); \ 
} \ 
private: \ 
static AddClonable _addClonable; 
#define PERSISTENT_IMPL(className) \ 
AddClonable className::_addClonable(#className, new className()); 
class Event : public Persistent { 
private: 
int _id; 
public: 
Event() : _id(0) {} 
virtual ~Event() {} 
int getId() { return _id; } 
protected: 
virtual void serialize(Archive& stream) 
{ 
    if (stream.isStoring()) 
     stream << _id; 
    else 
     stream >> _id; 
} 

PERSISTENT_DECL(Event) 
}; 
PERSISTENT_IMPL(Event) 

Persist.cpp

#include "Persist.h" 
#include <vector> 
#include <iostream> 
using namespace std; 
Archive& Archive::operator<<(int val) 
{ 
write(&val, sizeof(int)); 
return *this; 
} 

Archive& Archive::operator>>(int& val) 
{ 
read(&val, sizeof(int)); 
return *this; 
} 

Archive& Archive::operator<<(const string& str) 
{ 
int length = str.length(); 
*this << length; 
write(str.c_str(), sizeof(char) * length); 
return *this; 
} 

Archive& Archive::operator>>(string& str) 
{ 
int length = -1; 
*this >> length; 
vector<char> mem(length + 1); 
char* pChars = &mem[0]; 
read(pChars, sizeof(char) * length); 
mem[length] = NULL; 
str = pChars; 
return *this; 
} 
void ArchiveFile::write(const void* buffer, size_t length) 
{ 
_stream->write((const char*)buffer, length); 
if (!*_stream) 
    throw "ArchiveFile::write Error"; 
} 

void ArchiveFile::read(void* buffer, size_t length) 
{ 
_stream->read((char*)buffer, length); 
if (!*_stream) 
    throw "ArchiveFile::read Error"; 
} 
void Persistent::store(Archive& stream) const 
{ 
string className = typeid(*this).name(); 

className = className.substr(className.find(' ') + 1); 

stream << className; 

int ver = version(); 

stream << ver; 

stream.setDirection(true); 

const_cast<Persistent *>(this)->serialize(stream); 
} 
Persistent* Persistent::load(Archive& stream) 
{ 
string className; 
stream >> className; 

Clonable* clone = Clonables::Instance().create(className.c_str()); 
if (clone == NULL) 
    throw "Persistent::load : Error creating object"; 

auto_ptr<Clonable> delitor(clone); 

Persistent * obj = dynamic_cast<Persistent *>(clone); 
if (obj == NULL) { 
    throw "Persistent::load : Error creating object"; 
} 

int ver = -1; 

stream >> ver; 

if (ver != obj->version()) 
    throw "Persistent::load : unmatched version number"; 

stream.setDirection(false); 

obj->serialize(stream); 

delitor.release(); 

return obj; 
} 

Dynamics.h

#pragma once 
#include <string> 
using namespace std; 
#include <map> 


class Clonable 
{ 
public: 
virtual ~Clonable() {} 

virtual Clonable* createObj() = 0; 
}; 


class Clonables { 
private: 
typedef map<string, const Clonable*> NameToClonable; 
NameToClonable __clonables; 
private: 
Clonables() {} 
Clonables(const Clonables&);     // Prevent copy-construction 
Clonables& operator=(const Clonables&);  // Prevent assignment 
~Clonables() 
{ 
    for (NameToClonable::const_iterator it = __clonables.begin(); it !=  __clonables.end(); it++) { 
     const Clonable* clone = it->second; 
     delete clone; 
    } 
    __clonables.clear(); 
} 
public: 
static Clonables& Instance() 
{ 
    static Clonables instance; // Guaranteed to be destroyed.        
    return instance; // Instantiated on first use. 
} 
public: 
void addClonable(const char* className, const Clonable* clone) 
{ 
    string name = className; 
    NameToClonable::const_iterator it = __clonables.find(name); 
    if (it == __clonables.end()) { 
     __clonables[name] = clone; 
    } 
} 
Clonable* create(const char *className) 
{ 
    string name = className; 
    NameToClonable::const_iterator it = __clonables.find(name); 
    if (it == __clonables.end()) return NULL; 

    const Clonable* clone = it->second; 

} 
}; 
class AddClonable { 
public: 
AddClonable(const char* className, const Clonable* clone) { 
    Clonables::Instance().addClonable(className, clone); 
} 
}; 
+1

這是太多的代碼分析,並沒有MCVE我們嘗試自己編譯它。因此,沒有回答,只有一個評論:查看Boost序列化。 –

+0

您錯過了'Cloneables.create(...)'中的return語句以及可能更多的代碼。 – aslg

回答

0

您可以使用Boost.Serialization作爲示例。我想在這裏舉一個例子。您可以輕鬆地序列化您的對象運算符超載&。

#include <fstream> 
#include <boost/archive/text_oarchive.hpp> 
#include <boost/archive/text_iarchive.hpp> 
#include <boost/archive/binary_oarchive.hpp> 
#include <boost/archive/binary_iarchive.hpp> 

struct plane { 
    std::string id; 
    std::string name; 
    int x; 

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

    template<class Archive> 
    void serialize(Archive & ar, const unsigned int version) 
    { 
     ar & id; 
     ar & name; 
     ar & x; 
    } 
}; 

int serialization() 
{ 
    { 
     plane old_plane; 
     old_plane.id = "12345"; 
     old_plane.id = "plane foo"; 
     old_plane.x = 12345; 

     // boost::archive::text_oarchive oa(ofs); 
     std::ofstream ofs("filename"); 
     boost::archive::binary_oarchive oa(ofs); 
     oa << old_plane; 
    } 

    /////////////////////////////////////////////////////////////// 

    plane new_plane; 

    std::ifstream ifs("filename"); 
    //boost::archive::text_iarchive ia(ifs); 
    boost::archive::binary_iarchive ia(ifs); 

    ia >> new_plane; 

    /////////////////////////////////////////////////////////////// 

    std::cout << new_plane.id << " "; 
    std::cout << new_plane.name << " "; 
    std::cout << new_plane.x << std::endl; 


    return 0; 
}