J. *_*rez 5 c++ serialization mpi
假设这T是一个不包含指针的POD类型,我想序列化T(除了一些其他数据).我创建了以下函数来执行此操作:
template<class T> void serialize(const T& source, char*& dest)
{
*(T*)dest = source;
dest += sizeof(T);
}
template<class T> void deserialize(T& dest, char*& source)
{
dest = *(T*)source;
source += sizeof(T);
}
Run Code Online (Sandbox Code Playgroud)
这会导致任何问题,还是有任何编译器无法解决问题?换句话说,代码是:
template<class T> bool check_sanity(const T& obj)
{
std::unique_ptr<char[]> buffer { new int[sizeof(T)] };
serialize(obj, buffer);
T new_obj;
deserialize(new_obj, buffer);
return new_obj == obj;
}
Run Code Online (Sandbox Code Playgroud)
曾经回归虚假?(假设T是POD,没有人重载==运算符).
我正在编写这些序列化方法以与MPI一起使用,它们将在程序开始时用于分发簿记所需的一些数据,因此相同的程序将始终对数据进行序列化和反序列化.
我看到了几个问题。一个较小的:
*(T*)dest = source;
Run Code Online (Sandbox Code Playgroud)
IIRC,这是 UB,因为违反了别名规则(char *可以为任何其他指针别名,但这意味着您可以通过指针访问某个对象char *,但反之则不然,如您的示例所示)。
换句话说,代码会: ... 会返回 false 吗?
可能不是,但您提到序列化不仅仅是单个对象。
所以,主要问题是对齐:
std::unique_ptr<char[]> buffer { new char[sizeof(int) + 1] };
char x = 0;
int y = 0;
serialize(x, buffer);
serialize(y, buffer); // may crash or write into wrong location
Run Code Online (Sandbox Code Playgroud)
故障线路相同(但deserialize也受到影响):
*(T*)dest = source; // source is int, dest is not aligned
Run Code Online (Sandbox Code Playgroud)
编译器将假设 dest 已正确对齐,并使用 CPU 指令进行对齐存储(在 ARM 架构上,这将导致真正的问题)。
解决方案是使用 memcpy 代替:
memcpy(dest, &source, sizeof(T));
Run Code Online (Sandbox Code Playgroud)
无需担心性能。现代编译器能够很好地优化已知大小的对象的 memcpy。