我现在有一个stl:list,它包含一些基本对象和一些派生类。
我可以在没有任何问题的情况下加载和保存这个列表。与BOOST_CLASS_EXPORT(.)宏,所有内容都正常工作,直到我添加以下内容:
我需要一些包含列表中其他对象的指针的对象。
(不要再这么抽象了:这些都是“游戏对象”,它们引用了一些被称为“区域”的对象,它们都是从初级游戏类派生出来的。)
所以现在我正在序列化列表,并且每个对象都被单独序列化。
ar & characterList;“游戏”对象包含以下代码:
template<class Archive>
void save(Archive & ar, const unsigned int version) const {
ar & boost::serialization::base_object<M_Character>(*this);
ar & area; // If I add this line, it will crash
}
template<class Archive>
void load(Archive & ar, const unsigned int version) const {
ar & boost::serialization::base_object<M_Character>(*this);
ar & area; // This one as well
}所以我试图保存到指向这个区域的指针,但是在我添加这些行之后,程序会崩溃,我会释放.c,这告诉我我释放了两次相同的指针。Boost还会给我一个未注册的类错误。(我也导出了Area类,而且它也不需要
ar & area;)
因此,该区域将被序列化两次,因为首先该区域将从列表中保存,然后从对象中保存。
我怎样才能避免这种情况?是否可以第一次保存整个对象,第二次只保存指针?
或者我应该尝试完全不同的东西(从I列表中获取指针)
发布于 2014-05-04 16:02:49
好吧,我为你做了一个演示:
struct Area
{
Area(int i):id(i) {}
int id;
};
struct List : boost::noncopyable
{
std::vector<Area*> areas;
~List() {
std::for_each(areas.begin(), areas.end(), std::default_delete<Area>());
}
};
struct M_Character {
virtual ~M_Character() {}
};
struct GameObject : M_Character, boost::noncopyable
{
Area* area;
GameObject(Area* area = nullptr) : area(area) {}
};
BOOST_CLASS_EXPORT_GUID(GameObject, "GameObject")备注
areas的所有权。(因此,使列表不可复制;否则复制List将导致双重删除)List中的一个Area对象。因此,不应该删除正在销毁的区域(列表拥有它们!)示例程序:
int main()
{
List l;
for (int i = 0; i < 10; ++i)
l.areas.push_back(new Area(i));
std::unique_ptr<M_Character> obj, roundtrip;
// build original obj
obj.reset(new GameObject(l.areas[3])); // sharing the area pointer from the list
std::string const serialized = serialize(obj.get());
std::cout << serialized << '\n';
std::cout << "-------------------------------------------------\n";
// create roundtrip
roundtrip.reset(deserialize(serialized));
std::cout << "EQUAL? " << std::boolalpha << (serialized == serialize(roundtrip.get())) << "\n";
}您将注意到这是如何运行良好的(住在Coliru):
clang++ -std=c++11 -Os -Wall -pedantic main.cpp -lboost_system -lboost_serialization && ./a.out
22 serialization::archive 10 1 10 GameObject 1 0
0 1 0
1 2 1 0
2 3
-------------------------------------------------
EQUAL? true但是,您不会在Coliru上看到的是,这会泄漏内存。瓦兰告诉你,在反序列化过程中分配的4个字节丢失了--很明显,这是使用Area的GameObject。
但是嘿!在序列化指针时,Boost序列化不是要执行对象跟踪吗?
问得好。是的,确实如此。但是(这很容易被忽略),它只对同一对象图中的指针使用。因此,你可以通过
不会再有内存泄漏了!
全代码列表
#include <boost/archive/text_oarchive.hpp>
#include <boost/archive/text_iarchive.hpp>
#include <boost/serialization/serialization.hpp>
#include <boost/serialization/export.hpp>
#include <boost/serialization/vector.hpp>
struct Area
{
Area(int i):id(i) {}
int id;
private:
Area() { } // used only in deserialization
friend boost::serialization::access;
template<class Archive>
void serialize(Archive & ar, unsigned) { ar & id; }
};
struct List : boost::noncopyable
{
std::vector<Area*> areas;
~List() {
std::for_each(areas.begin(), areas.end(), std::default_delete<Area>());
}
private:
friend boost::serialization::access;
template<class Archive>
void serialize(Archive & ar, unsigned) { ar & areas; }
};
struct M_Character {
virtual ~M_Character() {}
private:
friend boost::serialization::access;
template<class Archive>
void serialize(Archive & /*ar*/, unsigned) { }
};
struct GameObject : M_Character, boost::noncopyable
{
Area* area;
GameObject(Area* area = nullptr) : area(area) {}
private:
friend boost::serialization::access;
template<class Archive>
void serialize(Archive & ar, unsigned) {
ar & boost::serialization::base_object<M_Character>(*this);
ar & area;
}
};
BOOST_CLASS_EXPORT_GUID(GameObject, "GameObject")
#include <sstream>
struct World : boost::noncopyable
{
List list;
GameObject* the_object;
World() : the_object(nullptr) {}
~World() { delete the_object; }
private:
friend boost::serialization::access;
template<class Archive>
void serialize(Archive & ar, unsigned) {
ar & list;
ar & the_object;
}
};
std::string serialize(World const& w)
{
std::stringstream ss;
boost::archive::text_oarchive oa(ss);
oa << w;
return ss.str();
}
void deserialize(std::string const& input, World& w)
{
std::stringstream ss(input);
boost::archive::text_iarchive ia(ss);
ia >> w;
}
int main()
{
World world;
for (int i = 0; i < 10; ++i)
world.list.areas.push_back(new Area(i));
// build original obj
world.the_object = new GameObject(world.list.areas[3]); // sharing the area pointer from the list
std::string const serialized = serialize(world);
std::cout << serialized << '\n';
std::cout << "-------------------------------------------------\n";
// create roundtrip
World roundtrip;
deserialize(serialized, roundtrip);
std::cout << "EQUAL? " << std::boolalpha << (serialized == serialize(roundtrip)) << "\n";
}https://stackoverflow.com/questions/23456360
复制相似问题