Reputation: 89
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:
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
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