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

欢乐的*_*aox 1 c++ compatibility std-variant

std::variant 是 union 的替代品。

但union可以通过网络安全地在另一个平台(不同的编译器或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));
Run Code Online (Sandbox Code Playgroud)

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

std::variant<int, double> v;
f.read(&v, sizeof(v));
Run Code Online (Sandbox Code Playgroud)

如果 std::variant 无法安全地通过网络传递。有图书馆提供吗?增强::变体?或者也许创建一个像 std::variant 一样的自定义实现?

Jan*_*n15 5

一般来说,C++ 中的 union、variant 或许多其他类型都不能将内存转储到文件中然后安全地读取。

当跨多个平台(即硬件)传输数据时,许多因素都会导致传输不安全:

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

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

如果问题更多地针对 的内存布局std::variant,则与std::variant任何其他std容器一样:内存布局是实现定义的。(这里的实现是指使用的标准库实现)。例如,某些标准库在 中进行小字符串优化std::string,它可以包含小字符串(例如,少于 32 个字符),而无需堆分配。有些则不然。因此,同一类型的内存布局存在很大差异。

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