【问题标题】:Input stream problem when using std::array使用 std::array 时的输入流问题
【发布时间】:2021-04-28 18:55:59
【问题描述】:

struct A 中没有bool b 时,代码有效。当bool b 存在时,ar & mat 给出“输入流错误”,但一个一个地注册std::array 的元素有效。这里有什么问题?

#include <fstream>
#include <boost/serialization/array.hpp>
#include <boost/archive/text_oarchive.hpp>
#include <boost/archive/text_iarchive.hpp>

struct A
{
    std::array<int, 3> mat;
    bool b;

    template<class Archive> void serialize(Archive& ar, const unsigned int version)
    {
        //ar & mat[0];
        //ar & mat[1];
        //ar & mat[2];
        ar & mat;
        ar & b;
    }
};


int main()
{
    {
        std::string fname = "save.sr";
        std::ofstream ofs(fname);
        boost::archive::text_oarchive oa(ofs);
        A a;
        oa << a;
    }

    {
        std::string fname = "save.sr";
        std::ifstream ifs(fname);
        boost::archive::text_iarchive ia(ifs);
        A a;
        ia >> a;
    }

    return 0;
}

【问题讨论】:

  • “ar & mat 给出错误”请分享这个错误。
  • 标题没让我写“输入流错误”,让我写“输入流问题”。然后我忘记在内容中提及错误信息了。

标签: c++ serialization boost boost-serialization


【解决方案1】:

我没有看到有什么问题。然后我用 asan/ubsan 看了下,发现域转换问题:http://coliru.stacked-crooked.com/a/edee75a22450d9ee

起初我认为在特定版本的 Boost[¹] 中可能会有错误。然后我恍然大悟。

有良性警告:

g++ -std=c++17 -O2 -Wall -pedantic -pthread main.cpp -fsanitize=address,undefined -lboost_serialization && ./a.out
/usr/local/include/boost/serialization/singleton.hpp:181:12: runtime error: reference binding to null pointer of type 'const struct extended_type_info_typeid'
/usr/local/include/boost/serialization/singleton.hpp:181:12: runtime error: reference binding to null pointer of type 'const struct oserializer'
/usr/local/include/boost/serialization/singleton.hpp:181:12: runtime error: reference binding to null pointer of type 'const struct extended_type_info_typeid'
/usr/local/include/boost/serialization/singleton.hpp:181:12: runtime error: reference binding to null pointer of type 'const struct iserializer'
/usr/local/include/boost/serialization/singleton.hpp:181:12: runtime error: reference binding to null pointer of type 'const struct extended_type_info_typeid'
/usr/local/include/boost/serialization/singleton.hpp:181:12: runtime error: reference binding to null pointer of type 'const struct extended_type_info_typeid'
/usr/local/include/boost/serialization/singleton.hpp:181:12: runtime error: reference binding to null pointer of type 'const struct oserializer'
/usr/local/include/boost/serialization/singleton.hpp:181:12: runtime error: reference binding to null pointer of type 'const struct extended_type_info_typeid'
/usr/local/include/boost/serialization/singleton.hpp:181:12: runtime error: reference binding to null pointer of type 'const struct iserializer'
/usr/local/include/boost/serialization/singleton.hpp:181:12: runtime error: reference binding to null pointer of type 'const struct extended_type_info_typeid'

然后我们得到域错误:

/usr/local/include/boost/archive/text_oarchive.hpp:65:50: runtime error: load of value 255, which is not a valid value for type 'bool'

注意oarchive 是如何进入它们的,并确认:

debug: "22 serialization::archive 17 0 0 0 0 3 -2049146224 32767 -2049145920 1
"

那些是……不确定的值。对于完整的积分域来说不是什么大问题,但对于 bool.所以,修复你的初始化:

struct A {
    std::array<int, 3> mat {};
    bool b {};

    template <class Ar> void serialize(Ar& ar, unsigned) {
        ar & mat & b;
    }
};

当然,你也可以使用其他样式:

std::array<int, 3> mat = {0,0,0};
bool b = false;

或者老式的构造函数:

std::array<int, 3> mat;
bool b;

A(std::array<int, 3> mat = {}, bool b = {}) : mat(mat), b(b) {}

等等。只要您确保初始化您的成员数据。

Fixed On COliru

#include <boost/archive/text_iarchive.hpp>
#include <boost/archive/text_oarchive.hpp>
#include <boost/serialization/array.hpp>
#include <iomanip>
#include <iostream>
#include <sstream>
#include <boost/version.hpp>

struct A {
    std::array<int, 3> mat = {0,0,0};
    bool b = false;

    template <class Ar> void serialize(Ar& ar, unsigned) {
        ar & mat & b;
    }
};

int main() {
    std::stringstream ss;
    {
        boost::archive::text_oarchive oa(ss);
        A a;
        oa << a;
    }

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

    {
        boost::archive::text_iarchive ia(ss);
        A a;
        ia >> a;
    }
}

打印

BOOST_VERSION: 107500
debug: "22 serialization::archive 18 0 0 0 0 3 0 0 0 0
"

[¹] 这就是大雁追逐的样子

【讨论】:

  • 我曾尝试初始化 std::array,但从未想过 bool 可能是问题的原因。谢谢。
猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 2015-12-13
  • 1970-01-01
  • 1970-01-01
  • 2016-05-23
  • 2017-07-20
  • 1970-01-01
  • 2020-01-12
相关资源
最近更新 更多