Boost Object_pool对象的Boost二进制序列化反序列化问题求助
解决Boost序列化与Object_pool结合的反序列化内存分配问题
看来你在把Boost序列化和object_pool结合使用时碰到了头疼的问题:序列化从池里拿的对象没问题,但反序列化时Boost总是自己在堆上分配新内存,完全绕开了你预先从池里分配好的对象;尝试用binary_object解决又遇到了编译错误。我来帮你理清问题根源,再给出两种可行的解决方案:
为什么你的binary_object尝试会编译失败?
你在反序列化时直接构造了临时的binary_object对象,但Boost的operator>>需要的是可修改的左值引用,临时对象是右值,没法绑定到非const的左值引用上——这就是你看到编译错误的直接原因。
正确的实现思路
要让反序列化的数据写入到object_pool预先分配好的对象里,核心是要避免Boost序列化自动触发内存分配。我们可以从两个方向入手:
方案一:直接序列化/反序列化对象实例(推荐)
最稳妥的方式是直接操作对象本身,而不是指针。这样反序列化时就能明确指定写入到你从池里拿到的对象中,完全规避Boost自动分配内存的逻辑:
#include <boost/archive/binary_iarchive.hpp> #include <boost/archive/binary_oarchive.hpp> #include <boost/pool/object_pool.hpp> #include <iostream> #include <sstream> #include <string> class MyClass { public: friend class boost::serialization::access; MyClass() : data(9) { std::cout << std::endl << "MyClass()" << std::endl; } template<class Archive> void serialize(Archive & ar, const unsigned int version) { ar & data; } ~MyClass() {} private: int data; }; int main() { try { boost::object_pool<MyClass> pool; // 从池获取对象并序列化(序列化对象本身,而非指针) MyClass *b = pool.construct(); std::stringbuf strbuf; boost::archive::binary_oarchive oa(strbuf); oa << *b; // 从池预分配反序列化目标对象 MyClass *a = pool.construct(); std::stringbuf strbufr(strbuf.str()); boost::archive::binary_iarchive ia(strbufr); // 反序列化到已分配好的对象实例中 ia >> *a; // 使用完毕后归还到对象池 pool.destroy(a); pool.destroy(b); } catch (boost::archive::archive_exception &e) { std::cout << std::endl << e.what() << std::endl; } return 0; }
方案二:正确使用binary_object
如果你确实需要用binary_object来直接拷贝对象的二进制内存(适合POD类型或不需要复杂序列化逻辑的场景),要注意必须传递左值给反序列化的operator>>:
#include <boost/archive/binary_iarchive.hpp> #include <boost/archive/binary_oarchive.hpp> #include <boost/serialization/binary_object.hpp> #include <boost/pool/object_pool.hpp> #include <iostream> #include <sstream> #include <string> class MyClass { public: MyClass() : data(9) { std::cout << std::endl << "MyClass()" << std::endl; } ~MyClass() {} int data; // 这里为了binary_object直接拷贝,把成员设为public(或者提供访问方式) }; int main() { try { boost::object_pool<MyClass> pool; MyClass *b = pool.construct(); std::stringbuf strbuf; boost::archive::binary_oarchive oa(strbuf); // 用binary_object序列化对象的二进制内存 oa << boost::serialization::binary_object(b, sizeof(MyClass)); MyClass *a = pool.construct(); std::stringbuf strbufr(strbuf.str()); boost::archive::binary_iarchive ia(strbufr); // 先构造binary_object左值,再传给反序列化操作 boost::serialization::binary_object target(a, sizeof(MyClass)); ia >> target; pool.destroy(a); pool.destroy(b); } catch (boost::archive::archive_exception &e) { std::cout << std::endl << e.what() << std::endl; } return 0; }
关键细节解释
- 当你序列化指针
oa << b时,Boost序列化会额外记录指针的内存地址等元数据,反序列化时会自动调用new分配内存,这就完全绕开了你的object_pool,导致池里预分配的对象被浪费,还没法回收Boost分配的内存。 - 直接序列化对象实例
oa << *b,反序列化到*a,就能完全复用object_pool的内存,既符合池的设计意图,也避免了内存泄漏。 binary_object是直接拷贝对象的二进制内存,不会调用类的serialize方法,也不会处理对象的构造逻辑,所以只适合可安全memcpy的类型(比如POD),如果你的类有复杂的成员(比如动态分配的内存、非POD类型),千万别用这种方式。
内容的提问来源于stack exchange,提问作者Jerry
相关产品推荐
相关产品推荐

