首页 > 解决方案 > 通过网络传递 std::variant 是否安全,跨平台

问题描述

std::variant 是联合的替代品。

但是联合可以通过网络安全地在另一个平台(不同的编译器或架构)中接收。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 不能安全地通过网络。有没有图书馆提供?提升::变体?或者也许创建一个像 std::variant 一样的自定义实现?

标签: c++compatibilitystd-variant

解决方案


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

当跨多个平台(即硬件)传输数据时,很多事情都会使传输不安全:

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

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

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

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


推荐阅读