1

As an experiment, I am trying to (de)serialize an std::map<std:string, ValueType> to/from a binary file, element by element.

I'm using something like this:

Live on Wandbox

void Save(const std::string& fname, const MapType& c)
{
    std::ofstream f(fname.c_str(), std::ios::binary);
    boost::archive::binary_oarchive oa(f, boost::archive::no_header);

    oa & c.size();
    for (auto& e : c)
    {
        oa & e.first;
        oa & e.second;
    }
}

void Load(const std::string& fname, MapType& c)
{
    std::ifstream f(fname.c_str(), std::ios::binary);
    boost::archive::binary_iarchive ia(f, boost::archive::no_header);

    int count;
    ia & count;
    for (int i = 0; i < count; ++i)
    {
        std::string key;
        ValueType value;
        ia & key;
        ia & value;
        c[key] = value;
    }
}

where, incidentally:

using ValueType = boost::variant<bool, int, double, std::string>;
using MapType = std::map<std::string, ValueType>;

After saving, I load the file back. The count is read correctly but the first key gives a bad allocation exception.

Any ideas?

The same code works well when I replace binary_oarchive and binary_iarchive by their respective text equivalents.

racanu
  • 79
  • 1
  • 9

1 Answers1

3

You save oa & c.size(); and then you load int count;ia & count;: if it happens that size_t and int have different sizes, the next load (ie the first ia & key; call) will be corrupted; then, I guess the std::string loader will read back a wrong string size causing a bad_alloc to be thrown.

Curiously, the count data results correctly read just by chance, due to your platform (un)lucky endianness and signed representation ...

In the text-based case the count data is parsed textually, hence serialization proceeds without error.

By the way, IIRC standard containers and variants are automatically serializable whenever their parameters are, so you don't need to write their serialization code by hand ...

Massimiliano Janes
  • 5,524
  • 1
  • 10
  • 22
  • I could have looked a million times and not see it... Thank you a lot. I know that containers are serializable. In fact, that's how I started and it worked well. I was just trying to experiment with it I'm ultimately planning to serialize it in memory and am looking to find the most compact format. I was trying to see if and how much overhead the std:map had. – racanu Jan 04 '18 at 19:31
  • About the overhead: https://stackoverflow.com/questions/22459726/boost-c-serialization-overhead/22464553#22464553 - In general, you won't do better than the library-supplied container serialization, especially in terms of performance. (E.g. std::vector optimizations for POD elements) – sehe Jan 05 '18 at 04:27