racanu
racanu

Reputation: 89

Bad allocation exception when deserializing std::string from boost::archive:binary_iarchive

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.

Upvotes: 1

Views: 1236

Answers (1)

Massimiliano Janes
Massimiliano Janes

Reputation: 5624

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 ...

Upvotes: 3

Related Questions