增强序列化:前向兼容性因输入流错误而失败

2023-12-01

遵循这个问题:Boost序列化子类我正在尝试支持使用 boost 序列化生成的存档的前向兼容性,但我在使用较旧的代码读取较新的存档时遇到问题:

    class A {
    public:
        A() {}
        virtual ~A() = default;

    private:
        friend class boost::serialization::access;
        template <class Archive> void serialize(Archive &ar, const unsigned int version) {
            ar &mAttributeFromA;
        }

        std::string mAttributeFromA = "mAttributeFromA";
    };
    BOOST_CLASS_VERSION(A, 0)

    class B : public A {
    public:
        B() {}

    private:
        friend class boost::serialization::access;
        template <class Archive> void serialize(Archive &ar, const unsigned int version)
        {
            ar &boost::serialization::base_object<A>(*this);
            ar &mAttributeFromB;
            if (version == 1)
                ar &mNewAttribute;
        }

        std::string mAttributeFromB = "mAttributeFromB";
        std::string mNewAttribute = "mNewAttribute";
    };

    BOOST_CLASS_VERSION(B, 1)


    class Manager {
    public:
        boost::ptr_vector<A> mListOfA; // can store A or B
    private:
        friend class boost::serialization::access;

        template <class Archive> void serialize(Archive &ar, const unsigned int /*version*/) { ar &mListOfA; }
    };
    BOOST_CLASS_VERSION(Manager, 0)


    int main() {
        Manager  mgr;
        mgr.mListOfA.push_back(new B);
        mgr.mListOfA.push_back(new B);

        std::ofstream ofs("myFile.txt");
        {
            boost::archive::text_oarchive oa(ofs);
            oa << mgr;
        }

        try {
            Manager  mgr2;
            std::ifstream ifs("myFile.txt");
            boost::archive::text_iarchive ia(ifs);
            ia >> mgr2;
            mgr2.mListOfA.at(0);
        } catch(boost::archive::archive_exception e)
        {
            e.what();
        }
    }
BOOST_CLASS_EXPORT(A)
BOOST_CLASS_EXPORT(B)

这将生成以下存档:

22 serialization::archive 13 0 0 0 0 2 3 1 B 1 1
0 1 0
1 15 mAttributeFromA 15 mAttributeFromB 13 mNewAttribute 3
2
3 15 mAttributeFromA 15 mAttributeFromB 13 mNewAttribute

如果我尝试使用相同的代码重新加载存档,一切都会完美运行。

但是,如果我尝试使用旧版本的代码加载存档:(类版本为 0 并且 mNewAttribute 消失了)

class B : public A {
    public:
        B() {}

    private:
        friend class boost::serialization::access;
        template <class Archive> void serialize(Archive &ar, const unsigned int version)
        {
            ar &boost::serialization::base_object<A>(*this);
            ar &mAttributeFromB;
        }

        std::string mAttributeFromB = "mAttributeFromB";
    };

    BOOST_CLASS_VERSION(B, 0)

反序列化给我带来了“输入流错误"

On Coliru

如何使用旧代码反序列化新存档?

- 编辑 - 奇怪的是,如果我添加AandB 对象内部的管理器正在工作。但是只有 A 或只有 B 就会失败......


您的类型不是多态的。版本控制可能与事物无关。

  • http://www.boost.org/doc/libs/1_60_0/libs/serialization/doc/serialization.html#衍生指针

    事实证明,序列化的对象类型取决于基类(在本例中为基类)是否是多态的。如果base不是多态的,也就是说,如果它没有虚函数,那么base类型的对象将被序列化。任何派生类中的信息都将丢失。如果这是我们想要的(通常不是)那么就不需要其他的努力了。

您可以轻松验证这一点:向量仅反序列化As:

Live On Coliru

#include <boost/serialization/serialization.hpp>
#include <boost/serialization/version.hpp>

class A {
  public:
    A(){}

  private:
    friend class boost::serialization::access;
    template <class Archive> void serialize(Archive &ar, const unsigned int version) { ar &mAttributeFromA; }

    std::string mAttributeFromA = "mAttributeFromA";
};
BOOST_CLASS_VERSION(A, 0)

class B : public A {
  public:
    B(){}

  private:
    friend class boost::serialization::access;
    template <class Archive> void serialize(Archive &ar, const unsigned int version) {
        ar &mAttributeFromB;
        if (version == 1)
            ar &mNewAttribute;
    }

    std::string mAttributeFromB = "mAttributeFromB";
    std::string mNewAttribute   = "mNewAttribute";
};

BOOST_CLASS_VERSION(B, 1)

#include <boost/ptr_container/serialize_ptr_vector.hpp>

class Manager {
  public:
    boost::ptr_vector<A> mListOfA; // can store A or B
  private:
    friend class boost::serialization::access;

    template <class Archive> void serialize(Archive &ar, const unsigned int /*version*/) { ar &mListOfA; }
};
BOOST_CLASS_VERSION(Manager, 0)

#include <boost/archive/text_oarchive.hpp>
#include <boost/archive/text_iarchive.hpp>
#include <sstream>

int main() {
    using namespace boost;

    std::stringstream ss;

    { 
        archive::text_oarchive oa(ss); 
        Manager mgr;
        mgr.mListOfA.push_back(new A);
        mgr.mListOfA.push_back(new B);

        oa << mgr;
    }

    std::cout << ss.str() << "\n";

    { 
        archive::text_iarchive ia(ss); 
        Manager mgr;

        ia >> mgr;

        std::cout << "Deserialized: " << mgr.mListOfA.size() << "\n";
    }
}

Prints

22 serialization::archive 13 0 0 0 0 2 2 1 0
0 15 mAttributeFromA 2
1 15 mAttributeFromA

Deserialized: 2

解决方案:

  1. 使层次结构真正具有多态性
  2. 添加基础对象的序列化
  3. 注册派生类型
  4. ???
  5. Profit!

样品(WIP)https://www.livecoding.tv/sehe/

Live On Coliru

#include <boost/serialization/serialization.hpp>
#include <boost/serialization/base_object.hpp>
#include <boost/serialization/export.hpp>
#include <boost/serialization/version.hpp>

class A {
  public:
    A(){}
    virtual ~A() = default;

  private:
    friend class boost::serialization::access;
    template <class Archive> void serialize(Archive &ar, const unsigned int version) {
        ar &mAttributeFromA; 
    }

    std::string mAttributeFromA = "mAttributeFromA";
};
BOOST_CLASS_VERSION(A, 0)

class B : public A {
  public:
    B(){}

  private:
    friend class boost::serialization::access;
    template <class Archive> void serialize(Archive &ar, const unsigned int version)
    {
        ar &boost::serialization::base_object<A>(*this);
        ar &mAttributeFromB;
        if (version == 1)
            ar &mNewAttribute;
    }

    std::string mAttributeFromB = "mAttributeFromB";
    std::string mNewAttribute   = "mNewAttribute";
};

BOOST_CLASS_VERSION(B, 1)
BOOST_CLASS_EXPORT(A)
BOOST_CLASS_EXPORT(B)

#include <boost/ptr_container/serialize_ptr_vector.hpp>

class Manager {
  public:
    boost::ptr_vector<A> mListOfA; // can store A or B
  private:
    friend class boost::serialization::access;

    template <class Archive> void serialize(Archive &ar, const unsigned int /*version*/) { ar &mListOfA; }
};
BOOST_CLASS_VERSION(Manager, 0)

#include <boost/archive/text_oarchive.hpp>
#include <boost/archive/text_iarchive.hpp>
#include <sstream>

int main() {
    using namespace boost;

    std::stringstream ss;

    { 
        archive::text_oarchive oa(ss); 
        Manager mgr;
        mgr.mListOfA.push_back(new A);
        mgr.mListOfA.push_back(new B);

        oa << mgr;
    }

    std::cout << ss.str() << "\n";

    { 
        archive::text_iarchive ia(ss); 
        Manager mgr;

        ia >> mgr;

        std::cout << "Deserialized: " << mgr.mListOfA.size() << "\n";
    }
}

Prints

22 serialization::archive 13 0 0 0 0 2 2 1 0
0 15 mAttributeFromA 3 1 B 1 1
1
2 15 mAttributeFromA 15 mAttributeFromB 13 mNewAttribute

Deserialized: 2
本文内容由网友自发贡献,版权归原作者所有,本站不承担相应法律责任。如您发现有涉嫌抄袭侵权的内容,请联系:hwhale#tublm.com(使用前将#替换为@)

增强序列化:前向兼容性因输入流错误而失败 的相关文章

随机推荐

  • 在 ng-if/*ngIf 中使用函数调用是一个不好的做法吗? [复制]

    这个问题在这里已经有答案了 在 ng if 中使用函数调用的返回值是一个不好的做法吗 它会影响消化周期 性能吗 与视图中使用的任何表达式一样 它将在每个摘要循环中重新评估 以查看其值是否已更改 从而确定是否必须删除该元素或将其添加到 DOM
  • 在 React 中的组件之间共享数据

    我正在开发一个使用 Meteor 和 React 作为视图引擎的应用程序 考虑这个图 React 隐藏另一个示例中的组件 当 C4 按钮单击事件被触发时 我需要更改 C2 组件状态 由于它们没有直接关系 我无法直接从 C4 访问 C2 状态
  • 寻找 FragmentStatePagerAdapter 的替代品

    我想找到 FragmentStatePagerAdapter PagerFragment 的替代品 因为我们都知道 FragmentStatePagerAdapter 至今仍处于崩溃状态 我和 github 上已经进行了很多尝试来制作一些模
  • 是否可以在 ARM (Android/Linux) 上的执行过程中更改字节序?

    我想知道是否可以在 ARM 平台上更改正在运行的应用程序中间执行的字节序 正如你们中的一些人所知 ARM 是双字节序 支持大字节序和小字节序 我想知道在 Android 或一般的 Linux 上是否可以设置单个应用程序在执行时使用不同的字节
  • 启用适用于 Android 的 Places SDK 时出现问题 (google)

    请帮忙 当我单击 Places SDK For android 访问页面以启用时 显示如下 您没有足够的权限查看此页面 追踪号码 4169288790274014457 有什么问题 我应该怎么做才能启用这个API 谢谢 无法启用 Place
  • HTML 和 XHTML 有什么区别?

    注意 这应该是这个问题的规范帖子 已经存在许多答案 但对各种差异的描述分散在各处 而且通常 他们还提供 我应该使用哪一个 的意见 我将在这里避免这种情况 如果您还有更多问题要问 或者您知道更多差异 请随时进行编辑 XHTML 和 HTML
  • 如何让我的 Facebook 应用程序在安装后自动请求所需的权限

    我正在使用 Facebook PHP SDK 2 1 2 我想做的就是几乎每个 Facebook 应用程序都具有req perms有 安装时会弹出愚蠢的 请求权限 框 我不想要用户必须按下的按钮 我不希望出现弹出窗口 我不想使用 FBML
  • 将“this”和参数传递给 addEventListener 函数而不使用绑定

    接下来禁用插件时 引导插件中的删除事件监听器不起作用 我正在探索其他可能性 除了使用bind 并缓存绑定函数 有没有办法使用 this 并传递参数 works fine but can t pass argeement contextMen
  • UITableView 滑动手势需要近乎完美的准确性

    我正在为使用自定义 UITableViewCell 子类的 UITableView 开发自定义滑动事件 我包括了UIGestureRecognizerDelegate在我的标题中 并将其放入viewDidLoad UISwipeGestur
  • 在 GNU 汇编器宏中引用操作数/参数

    我目前正在尝试理解的概念汇编语言中的宏 特别是在 GNU 汇编器中 IA 32 x86 的 AT T 语法 我大学的幻灯片内容如下 How to define a macro macro write string movl string e
  • 在 Magento 中通过 SOAP 将产品添加到购物车时设置自定义选项

    我正在尝试使用购物车产品添加用于将具有自定义选项的产品添加到购物车的 SOAP API 下面是我为产品参数传递的数组 我有一个自定义选项 id 1 下拉列表中的选定值 id 为 2 您可以查看产品在这里 array size 1 0 gt
  • Android 快捷方式位图启动器图标大小

    我无法找到快捷方式的正确启动器图标大小 在我的 Nexus 7 2 上 android R dimen app icon size 参见代码 的值为 96 像素 但如果我在我的主屏幕截图上测量其他应用程序的真实图标大小 它是 120 像素
  • 类型错误:$ 在 jquery 中未定义

    我正在尝试在基于 WordPress 的网站上使用 jquery 中的 tabcordion 库 tabcordion javascript 文件正在 排队 并出现在 jquery 文件之后 因此该位看起来不错 jquery 代码的开头是
  • SQL CLR - 从 2008 R2 迁移到 2012。

    我在 SQL 2008 R2 上有一堆 SQL CLR 程序集 这些程序集以 Net Framework 3 5 为目标 鉴于 SQL 2008 支持 2 0 NET Framework 版本 我假设 SQL 从系统 GAC 加载安全程序集
  • 比较 mongo find 方法中的 2 个日期

    我有 mongo 文档 其中包含 last active 日期和创建日期 我想搜索所有包含以下内容的文档daylast active 不等于day创建的 但我不知道如何编写查询 在 MySQL 中我会这样写 WHERE DATE FORMA
  • 一键发布时:执行发布异常:已添加具有相同密钥的项目

    我意识到有十亿人询问过这个错误 但我已经查看了所有人 我的好像不一样我没有收到任何类型的源代码错误 没有堆栈跟踪 也没有任何有用的信息 因为在我的 MVC NET 项目上单击 发布 后立即发生错误 它只是一个对话框 仅此而已 没有其他事情发
  • Powershell 可执行文件未输出到 STDOUT

    来自 powershell 脚本 带有nuget安装并在路径上 我正在尝试执行可执行文件 net 如果这很重要 但由于某种原因 我无法在命令窗口中显示 STDOUT nuget install mdoc OutputDirectory pa
  • ES6 需要配置 webpack 吗?

    我有一个 Angular 应用程序 其中包含针对 ES6 的 tsconfig 文件 compileOnSave false compilerOptions allowJs true baseUrl outDir dist out tsc
  • 如何手动设置语料库中的文档ID?

    我正在从数据帧创建 Copus 我将其作为VectorSource因为我只想将一列用作文本源 这可以找到 但是我需要语料库中的文档 ID 来匹配数据帧中的文档 ID 文档 ID 存储在原始数据框中的单独列中 df lt as data fr
  • 增强序列化:前向兼容性因输入流错误而失败

    遵循这个问题 Boost序列化子类我正在尝试支持使用 boost 序列化生成的存档的前向兼容性 但我在使用较旧的代码读取较新的存档时遇到问题 class A public A virtual A default private friend