【问题标题】:Does using different Boost versions affect serialization and deserialization?使用不同的 Boost 版本会影响序列化和反序列化吗?
【发布时间】:2021-12-14 12:44:24
【问题描述】:

我正在使用 Boost 进行二进制序列化和反序列化的 C++ 项目。 Boost 版本 1.61 中已经存在序列化功能我使用 Boost 版本 1.77 添加了整个反序列化功能,现在我在读取二进制文件时遇到了问题。所以,我的问题是这种反序列化版本的差异如何影响这个过程?因为我无法正确读取二进制文件。

使用 Boost 版本 1.61 进行序列化的代码

#include <boost/archive/binary_oarchive.hpp>
#include <fstream>
#include <string>

class Frame{
public:
    std::string str;
};
template <typename Archive>
void serialize(Archive& ar, Frame& f, const unsigned int version) {
    ar& f.str;
}

uint32_t main () {
    Frame f={"Frame example"};
    std::ofstream ofs;
    ofs.open("BinaryFile.bin",std::ios::out, std::ios::binary);
    boost::archive::text_oarchive write(ofs,boost::archive::no_header);
    write << f;
    ofs.close();
}

使用 boost 1.77 版本进行反序列化的代码

#include <boost/archive/binary_iarchive.hpp>
#include <fstream>
#include <string>

class Frame{
public:
    std::string str;
};
template <typename Archive>
void serialize(Archive& ar, Frame& f, const unsigned int version) {
    ar& f.str;
}

uint32_t main () {
    Frame f;
    std::ofstream ofs;
    ofs.open("BinaryFile.bin",std::ios::in, std::ios::binary);
    boost::archive::text_oarchive read(ofs,boost::archive::no_header);
    read >> f;
    ofs.close();
}

这只是一个示例代码,我使用的框架不同但方法相同。

【问题讨论】:

  • 您能否提供一个进行序列化和反序列化的代码的小示例,例如使用 Boost 1.61 进行序列化,而使用 Boost 1.77 的相同代码无法反序列化?
  • TL;DR : 需要两边的 boost 版本相同,否则不保证能正常工作;我过去也遇到过同样的问题,最后放弃了使用 boost。另一方面,Protobuf 应该保证一定的兼容性。
  • @Eljay 我已经添加了示例代码,您可以查看一下。
  • @pptaszni 感谢您的建议。
  • 感谢您提供代码。它是否为您编译并运行?它没有为我编译。

标签: c++ boost


【解决方案1】:

具有向后兼容性。但它需要存在存档标头,以便库可以检测反序列化所需的版本支持。

如果没有标头,就无法判断,因此库必须假定它是最新版本。

删除应该可以工作,实时查看:

在我的机器上,读取端使用 Boost 1.77.0 中的相同文件(在 wandbox 上不可用):

Success: Frame example

总结

您可能应该切换文件格式以使用标题。这可能需要某种转换工具。如果一切都失败了,您可能会选择通过文件名/扩展名来区分版本。这很脆弱,但如果它是你唯一可以控制的东西,它可能会拯救你。

【讨论】:

  • 添加了现场演示
  • 这仍然不起作用。 boost 1.61.0 的存档版本是 14,而 boost 1.77.0 的存档版本是 19,文本文件可以工作,但二进制文件不能工作。
  • 我也尝试过使用 boost 1.61 进行序列化和反序列化,甚至这对我不起作用。
  • @Rav 请分享最少的代码,以便我们了解问题所在
  • @Rav 盲目猜测,你有 "std::ios::out, std::ios::binary" 这显然是错误的。请注意我在现场演示中是如何编写的
【解决方案2】:

编码稳定性不是 boost 序列化本身的属性,而是在每个存档的基础上处理。

您可以在存档中使用get_library_version() 来检查增强版本之间的兼容性。

返回一个无符号整数,其中包含序列化库的当前版本号。每次以这样的方式更改库时,此数字都会增加,从而可以更改某些类型的序列化。 [...]

【讨论】:

  • 所以使用相同的版本是一个简单的选择?
  • 在我看来,无论如何你都应该检查get_library_version()。即使只是简单地将其与硬编码常量进行检查,也足以拦截令人讨厌的意外。这不是如果序列化和反序列化之间的版本不同步发生的问题,而是何时的问题。这可能需要几年的时间,但我可以保证你迟早会遇到它。
  • @Rav “所以使用相同的版本是一个简单的选择吗?” -- 简单吗?对于一个开发人员的项目,是的。长期可持续?没有。
猜你喜欢
  • 2012-09-05
  • 1970-01-01
  • 1970-01-01
  • 2015-08-06
  • 2015-03-19
  • 2012-03-03
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多