I am investigating a port from a non-standard to a standard string in an application that uses boost::archive. The non standard string has its (de-)serialization defined in the non-intrusive style as shown in the example below. Serialization and deserialization works as expected, but when the ported application receives an old message, it crashes with a bad allocation. This is caused by the insertion of 5 bytes (all zero) before the size of the string.
What causes the insertion of these 5 extra bytes? Is this some kind of magic marker?
Example:
#include <iostream>
#include <string>
#include <sstream>
#include <boost/serialization/split_free.hpp>
#include <boost/archive/binary_oarchive.hpp>
struct own_string { // simplified custom string class
std::string content;
};
namespace boost
{
namespace serialization
{
template<class Archive>
inline void save(
Archive & ar,
const own_string & t,
const unsigned int /* file_version */)
{
size_t size = t.content.size();
ar << size;
ar.save_binary(&t.content[0], size);
}
template<class Archive>
inline void load(
Archive & ar,
own_string & t,
const unsigned int /* file_version */)
{
size_t size;
ar >> size;
t.content.resize(size);
ar.load_binary(&t.content[0], size);
}
// split non-intrusive serialization function member into separate
// non intrusive save/load member functions
template<class Archive>
inline void serialize(
Archive & ar,
own_string & t,
const unsigned int file_version)
{
boost::serialization::split_free(ar, t, file_version);
}
} // namespace serialization
} // namespace boost
std::string string_to_hex(const std::string& input)
{
static const char* const lut = "0123456789ABCDEF";
size_t len = input.length();
std::string output;
output.reserve(2 * len);
for (size_t i = 0; i < len; ++i)
{
const unsigned char c = input[i];
output.push_back(lut[c >> 4]);
output.push_back(lut[c & 15]);
}
return output;
}
void test_normal_string()
{
std::stringstream ss;
boost::archive::binary_oarchive ar{ss};
std::string test = "";
std::cout << string_to_hex(ss.str()) << std::endl;
ar << test;
//adds 00 00 00 00 00 00 00 00
std::cout << string_to_hex(ss.str()) << std::endl;
}
void test_own_string()
{
std::stringstream ss;
boost::archive::binary_oarchive ar{ss};
std::string test = "";
own_string otest{test};
std::cout << string_to_hex(ss.str()) << std::endl;
ar << otest;
//adds 00 00 00 00 00 00 00 00 00 00 00 00 00
std::cout << string_to_hex(ss.str()) << std::endl;
}
int main()
{
test_normal_string();
test_own_string();
}