0

When there is no bool b in struct A, the code works. When bool b is there, ar & mat gives "input stream error" but registering elements of std::array one by one works. What's wrong here?

#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;
}
2
  • 1
    "ar & mat gives error" please share this error. Commented Jan 24, 2021 at 22:49
  • The title didn't let me write "input stream error" and made me to write "input stream problem". Then I forgot to mention the error message in the content. Commented Jan 24, 2021 at 22:51

1 Answer 1

1

I didn't see what could be wrong. Then I looked with asan/ubsan and found domain conversion issues: http://coliru.stacked-crooked.com/a/edee75a22450d9ee

At first I thought maybe there would be a bug in a specific version of Boost[¹]. Then it dawned on me.

There are benign warnings:

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'

And then we got the domain error:

/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'

Notice how it is the oarchive that runs into them, and confirm:

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

Those are... indeterminate values. Not a big problem for a complete integral domain, but it is for bool. So, fix your initialization:

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

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

Of course, you can use other styles:

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

Or the old-fashioned constructor:

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

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

Etc. as long as you make sure you initialize your member data.

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;
    }
}

Prints

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

[¹] This is what a wild goose chase looks like

Sign up to request clarification or add additional context in comments.

1 Comment

I have tried to initialize std::array but never thought the bool might be the cause of the problem. Thank you.

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.