Boost.Serialization 在不同平台上的序列化是不是不同?

Posted

技术标签:

【中文标题】Boost.Serialization 在不同平台上的序列化是不是不同?【英文标题】:Does Boost.Serialization serialize differently on different platforms?Boost.Serialization 在不同平台上的序列化是否不同? 【发布时间】:2011-04-12 03:38:22 【问题描述】:

我使用 Boost.Serialization 来序列化 std::map。代码是这样的

void Dictionary::serialize(std::string & buffer)

  try 
    std::stringstream ss;
    boost::archive::binary_oarchive archive(ss);
    archive << dict_; 
    buffer = ss.str();
   catch (const std::exception & ex) 
    throw DictionaryException(ex.what());
  


void Dictionary::deserialize(const char * const data, int length)

  try 
    namespace io = boost::iostreams;
    io::array_source source(data, length);
    io::stream<io::array_source> in(source);
    boost::archive::binary_iarchive archive(in);
    archive >> dict_;
   catch (const std::exception & ex) 
    throw DictionaryException(ex.what());
  

我在 Mac Snow Leopard 和 Ubuntu Lucid 10.04 上编译并测试了代码。两个系统上都有 Boost 1.40。在 Mac 上,我自己构建了代码。在 Ubuntu 机器上,我通过 aptitude 获得了二进制文件。

问题:当我在 Mac 上序列化地图时,我无法在 Ubuntu 机器上反序列化它。如果我尝试,我会得到一个invalid signature异常。

【问题讨论】:

【参考方案1】:

尝试使用text_iarchivetext_oarchive 而不是二进制存档。来自documentation

在本教程中,我们使用了 特定的存档类 - text_oarchive 用于保存和 text_iarchive 用于加载。文本 档案将数据呈现为文本,并且是 跨平台便携。此外 对于文本档案,图书馆包括 本机二进制数据的归档类 和 xml 格式的数据。接口 所有档案类都是相同的。 一旦定义了序列化 对于一个类,该类可以是 序列化为任何类型的存档。

【讨论】:

请注意,这可能会对您的应用程序的性能产生非常显着的影响。【参考方案2】:

boost:archive::binary_xarchive 目前不可移植 根据我的解释,这意味着不同平台上可能存在差异。文本存档在所有系统上为您提供相同的输入/输出行为。 还有一个相关的 TODO 条目试图解决二进制存档的可移植性问题:TODO Entry

【讨论】:

【参考方案3】:

text_archives 的性能比 binary_archive 慢很多。如果性能是你的事,你可以试试an unofficial portable binary archiveeos_portable_archive。我已经用它在 Windows 上成功地序列化了 32 位和 64 位的数据。你可以试试看。

只需要将文件放在您的序列化目录中。那里的文件不是最新的 boost 版本 (1.44.0),但您只需要进行 2 次非常微不足道的调整即可使其正常工作(您的编译器会告诉您非常明显的错误消息)。

【讨论】:

eos_portable_archive 不支持序列化 wstrings,这对我来说破坏了交易。 boost 附带了一个portable_binary_iarchive.hpp(在boost/libs/serialization/example 中),它没有这个限制,对我来说工作得很好。它还有一些其他限制documented here @Omer Raviv:可移植存档不支持序列化浮点类型,当时这对我来说是个坏交易。事实上,我意识到 boost::serialization adds horrendous size 到我放弃它并推出自己的可执行文件。我不确定新版本的 boost 是否解决了这个问题。 更新: EOS 便携式存档 v5.0 现在也有 supports wstring。新家是here。【参考方案4】:

我同意答案,但想添加一个澄清说明。您可能会认为这是一个令人讨厌的疏忽,但实际上提出并实现可移植的二进制格式并不是一件容易的事。我知道的唯一能有效解决问题的标准二进制是ASN.1。

XML 旨在解决同样的问题,但通常是在文本中解决。有一个名为 Fast Infoset 的 XML 搭载标准,它允许 XML 以二进制形式对数据进行编码,但它使用 ASN.1。

【讨论】:

哇。不确定我以前是否听过“有效”和“ASN.1”如此接近。但是,我曾经不得不调试别人编写的 ASN.1 解析器,所以我倾向于将它与数小时的极度痛苦联系起来。实际上可能不是 ASN.1 的错。 我不争辩。我的错。我应该阅读 Boost.Serialization 文档。文字就好了。 @Steve Jessop - 根本不是你的错,但我认为这主要是任务的错。那里可能有一些通用的 ASN.1 解析器,但我见过的每个解析器都只是解析它期望从对方那里得到的 ASN.1 的子集。即使这是一项艰巨的任务。 毫无疑问,我正在调试的解析器就是这种情况。它仅用于 X.509 证书和相关实体。

以上是关于Boost.Serialization 在不同平台上的序列化是不是不同?的主要内容,如果未能解决你的问题,请参考以下文章

找不到 boost::serialization 的成员

我可以告诉 Boost.MPI 哪个类版本与 Boost.Serialization 一起使用吗?

boost::serialization v1.59 和 v1.60 之间的归档版本

使用 boost::serialization 时如何刷新文件缓冲区?

如何为 boost::serialization 指定一个 nvp 包装器?

使用 boost::serialization 保存数据时出现 Seg 错误