【发布时间】:2017-12-02 14:13:49
【问题描述】:
我正在使用 boost::archive 的应用程序中调查从非标准到标准字符串的端口。非标准字符串的(反)序列化以非侵入式风格定义,如下例所示。序列化和反序列化按预期工作,但是当移植的应用程序收到旧消息时,它会因分配错误而崩溃。这是因为在字符串大小之前插入了 5 个字节(全为零)。
是什么导致了这 5 个额外字节的插入?这是某种魔法标记吗?
例子:
#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();
}
【问题讨论】:
-
什么是“旧消息”?关于额外的字节,我猜这只是版本控制数据......
-
旧消息是使用了自定义字符串的消息。
-
@choeger 只需修正问题措辞即可消除混乱! +1 优秀的独立样本
-
size_t 的大小可能因编译器、编译器版本和平台而异。序列化非固定大小的类型往往会破坏大多数序列化协议。
-
@Yakk 不是这样。追踪这一点实际上很有趣
标签: c++ serialization boost