【问题标题】:is it safe to pass std::variant over the network, cross platform通过网络传递 std::variant 是否安全,跨平台
【发布时间】:2020-02-24 01:52:55
【问题描述】:

std::variant 是 union 的替代品。

但联合可以通过网络安全地在另一个平台(不同的编译器或架构)接收。 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 的自定义实现?

【问题讨论】:

  • 你甚至不应该像这样通过网络传递int,更不用说std::variant了。使用序列化库或自行序列化。
  • 实际上隐藏了一个很好的问题:仅包含 POD 的变体本身是否是 POD。重新阅读变体的(简短的)定义,它对这个主题保持沉默,所以我会说它是未指定的。
  • @SamVarshavchik 至少在 C++20 中是这样,不知道它是否被认为是针对 C++17 的缺陷报告。从p0602r4 更改结果。
  • @OP:如果f 是标准流,您的代码也无法编译。您需要明确地将 reinterpret_castchar* 才能编译。

标签: c++ compatibility std-variant


【解决方案1】:

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

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

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

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

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

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

【讨论】:

    猜你喜欢
    • 2011-01-09
    • 2018-07-20
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2017-05-19
    • 1970-01-01
    • 2011-01-13
    相关资源
    最近更新 更多