如何解决自定义 boost 序列化输入存档仅在使用向量时失败 (boost::archive::archive_exception)
我正在使用 boost 序列化,并且我编写了一个源自 boost 二进制输入存档的自定义输入存档。事件虽然这个类现在与 boost 的 binary_iarchive 完全一样,但在反序列化原始类型的 boost::archive::archive_exception
时我得到一个 std::vector
。我没有遇到任何序列化问题,例如std::string
或 std::vector<std::string>
。
完整代码如下:
InputArchive 实现:
#ifndef __INPUT_ARCHIVE_H
#define __INPUT_ARCHIVE_H
#include <boost/archive/binary_iarchive.hpp>
#include <boost/archive/impl/basic_binary_iprimitive.ipp>
#include <boost/archive/impl/basic_binary_iarchive.ipp>
class InputArchive;
using iarchive = boost::archive::binary_iarchive_impl<
InputArchive,std::istream::char_type,std::istream::traits_type>;
class InputArchive : public iarchive {
friend class boost::archive::detail::interface_iarchive<InputArchive>;
friend class boost::archive::basic_binary_iarchive<InputArchive>;
friend class boost::archive::load_access;
public:
template<typename ... Args>
InputArchive(Args&& ... args)
: iarchive(std::forward<Args>(args)...,boost::archive::archive_flags::no_header)
{}
};
#endif
虚拟类,用于测试目的:
#ifndef __DUMMY_PRODUCT_H
#define __DUMMY_PRODUCT_H
#include <vector>
#include <boost/serialization/vector.hpp>
#include <string>
#include <boost/serialization/string.hpp>
struct dummy_product {
std::vector<char> data;
template<typename A>
void serialize(A& ar,const unsigned int version) {
ar & data;
}
};
#endif
以及使用存档的示例代码:
#include <boost/archive/binary_oarchive.hpp>
#include "InputArchive.hpp"
#include "DummyProduct.hpp"
#include <string>
#include <sstream>
#include <iostream>
int main() {
dummy_product p;
p.data.resize(16);
std::string buffer;
{
std::stringstream ss_value;
boost::archive::binary_oarchive oa(ss_value,boost::archive::archive_flags::no_header);
oa << p;
buffer = ss_value.str();
}
for(auto i : buffer) {
std::cout << (int)i << " ";
}
std::cout << std::endl;
{
std::stringstream ss_value(buffer);
//boost::archive::binary_iarchive ia(ss_value,boost::archive::archive_flags::no_header);
InputArchive ia(ss_value);
ia >> p;
}
}
此代码抛出以下异常:
terminate called after throwing an instance of 'boost::archive::archive_exception'
what(): input stream error
如您所见,InputArchive 只是从相应的 boost::archive::binary_iarchive_impl
继承而没有执行任何其他操作。如果我用 boost::archive::binary_iarchive
替换 InputArchive,则没有问题。如果我在 std::string
中使用 std::vector<char>
而不是 dummy_product
也没有问题。异常似乎只发生在原始类型的 std::vector
上。
知道这个问题是从哪里来的吗? 我使用的是 boost 1.75.0 和 gcc 8.3.0。
解决方法
缺少两个主要的东西:
-
问题。如您所见,InputArchive 只是从适当的 boost::archive::binary_iarchive_impl 继承而没有其他任何操作。
A. 是的,但不是以适当的方式。您的构造函数忘记初始化存档。只需转发到基类构造函数就完成了一半的工作:
enum { forced_flags = boost::archive::archive_flags::no_header }; InputArchive(std::istream & is,unsigned int flags = 0) : iarchive(is,flags | forced_flags) { init(flags | forced_flags); } InputArchive(std::streambuf & bsb,unsigned int flags = 0) : iarchive(bsb,flags | forced_flags) { init(flags | forced_flags); }
-
接下来,对允许按位二进制输出的存档的原始类型进行了优化。你的就是其中之一,所以你需要告诉 Boost:
BOOST_SERIALIZATION_USE_ARRAY_OPTIMIZATION(InputArchive)
-
为了真的很酷,您可能还想正确地获得注册到存档类型的多态类型的类型信息。如果你这样做了,你也想告诉 Boost :
BOOST_SERIALIZATION_REGISTER_ARCHIVE(InputArchive)
松散的笔记:
- 我不确定
friends
的用途。这可能是我的性格缺陷 - 考虑将事物移动到命名空间中,例如
::iarchive
不会无缘无故地污染全局命名空间。 [另外,考虑使用 CRTP 并在类定义中拼出名称。]
现在可以使用了
#ifndef __INPUT_ARCHIVE_H
#define __INPUT_ARCHIVE_H
#include <boost/archive/binary_iarchive.hpp>
#include <boost/archive/impl/basic_binary_iprimitive.ipp>
#include <boost/archive/impl/basic_binary_iarchive.ipp>
class InputArchive;
using iarchive = boost::archive::binary_iarchive_impl<
InputArchive,std::istream::char_type,std::istream::traits_type>;
class InputArchive : public iarchive {
enum {
forced_flags = boost::archive::archive_flags::no_header
};
//friend class boost::archive::detail::interface_iarchive<InputArchive>;
//friend class boost::archive::basic_binary_iarchive<InputArchive>;
//friend class boost::archive::load_access;
public:
InputArchive(std::istream & is,unsigned int flags = 0) :
iarchive(is,flags | forced_flags)
{
init(flags | forced_flags);
}
InputArchive(std::streambuf & bsb,unsigned int flags = 0) :
iarchive(bsb,flags | forced_flags)
{
init(flags | forced_flags);
}
};
// required by export
BOOST_SERIALIZATION_REGISTER_ARCHIVE(InputArchive)
BOOST_SERIALIZATION_USE_ARRAY_OPTIMIZATION(InputArchive)
#endif
#ifndef __DUMMY_PRODUCT_H
#define __DUMMY_PRODUCT_H
#include <vector>
#include <boost/serialization/vector.hpp>
#include <string>
#include <boost/serialization/string.hpp>
struct dummy_product {
std::vector<char> data;
template<typename A>
void serialize(A& ar,unsigned) {
ar & data;
}
};
#endif
#include <boost/archive/binary_oarchive.hpp>
//#include "InputArchive.hpp"
//#include "DummyProduct.hpp"
#include <string>
#include <sstream>
#include <iostream>
#include <iomanip>
int main() {
dummy_product p;
p.data.resize(16);
std::string buffer;
{
std::stringstream ss_value;
boost::archive::binary_oarchive oa(ss_value,boost::archive::archive_flags::no_header);
oa << p;
buffer = ss_value.str();
}
for(int i : buffer) {
std::cout << std::hex << std::setw(2) << std::setfill('0') << (int)i << " ";
}
std::cout << std::endl;
{
std::stringstream ss_value(buffer);
// boost::archive::binary_iarchive ia(ss_value,boost::archive::archive_flags::no_header);
InputArchive ia(ss_value);
ia >> p;
}
}
印刷品
00 00 00 00 00 10 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00
版权声明:本文内容由互联网用户自发贡献,该文观点与技术仅代表作者本人。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如发现本站有涉嫌侵权/违法违规的内容, 请发送邮件至 dio@foxmail.com 举报,一经查实,本站将立刻删除。