通过网络,跨平台传递std :: variant是否安全

问题描述 投票:0回答:2

std :: variant是联合的替代。

但是联合可以通过网络传递并安全地在另一个平台(不同的编译器或arch)中接收。 std :: variant可以这样做吗?

例如,我有两台机器A和B。A是Windows,MSVC 19.4。 B是Linux,gcc(或其他编译器,例如MSVC 17)。我在A(或B)下编译代码:

std::variant<int, double> v = 1; // holds int.
f.write(&v, sizeof(v));

B可以使用以下代码从同一文件中读取正确的值吗?

std::variant<int, double> v;
f.read(&v, sizeof(v));

如果std :: variant无法安全通过网络。有图书馆提供吗? boost :: variant?还是创建一个类似于std :: variant的自定义实现?

c++ compatibility std-variant
2个回答
3
投票

通常,C ++中的联合,变体或许多其他类型都不能被内存转储到文件中,然后安全地读取。

[跨多个平台(意味着硬件)传输数据时,许多事情会使传输不安全:

  • Endianness(当今大多数机器,例如x86都是低端字节序)
  • 大小(例如,您所指的int类型在一个平台上可以是4个字节,在另一个平台上可以是8个字节。]
  • 一个字节有多少位(CHAR_BIT,通常为8,这仅适用于少数奥术平台)
  • 使用的浮点实现。 (IEEE-754如今已被大多数硬件使用,但是C ++标准不需要这样做)

因此,跨平台传输数据的唯一安全方法是使用标准化的中间数据格式,通常称为序列化。许多库可以帮助您。一些要研究的是

如果问题更针对std::variant的内存布局,则std::variant的情况与任何其他std容器相同:内存布局是实现定义的。 (此处的实现表示所使用的标准库实现)。例如,某些标准库在std::string中进行了小的字符串优化,其中可以包含没有堆分配的小的字符串(例如,少于32个字符)。有些没有。因此,对于同一类型,您在内存布局上有很大的不同。

因此,您要么保证发送方和接收方都具有相同的硬件和标准库实现,要么使用序列化库来确保与发送的数据相同的数据到达。


0
投票

您不能只读取非POD类型的指针。

没有标准序列化,但是您可以使用std::visit进行自己的序列化>

boost::variant的序列化已在boost/serialization/variant.hpp中实现

P.S。我不确定union在这方面是否安全...填充在不同平台/编译器上可能会有所不同

© www.soinside.com 2019 - 2024. All rights reserved.