【问题标题】:using union as serializer for boost::asio使用 union 作为 boost::asio 的序列化程序
【发布时间】:2013-01-30 09:23:06
【问题描述】:

我想知道是否没有人使用联合来序列化 boost::asio 发送方/接收方的结构。我已经搜索过一些东西,但我发现的(目前)都是thisthis 之类的例子。

所以我这样做了:

struct ST {
  short a;
  long b;
  float c;
  char c[256];
}
... 

void sender::send(const ST &_packet) {
  union {
    const ST &s;
    char (&c)[sizeof(ST)];
  }usc = {_packet};

  socket.send_to(boost::asio::buffer(usc.c, sizeof(ST)), endpoint);
}
...

ST var = {1234, -1234, 1.4567, "some text"};
sercer.send(var);

所以我现在的问题是,对基本数据类型进行序列化是不好的做法吗?

我知道我不能直接发送 var 大小的字符串,因此我可以使用 boost::serialization。

【问题讨论】:

  • 恕我直言,是的,这太可怕了。为什么不直接将static_cast 发送到void*,然后通过它。它会更具可读性,并且更能代表您似乎正在尝试做的事情。
  • 我认为这是一种不好的做法,因为您违反了严格的别名规则并因此调用了未定义的行为。不过,按照激进 7 的建议使用 static_cast 也无济于事。

标签: c++ serialization boost boost-asio unions


【解决方案1】:

这确实是不好的做法。您发送的是(应该是)一个字节序列,其中包含系统上联合中任何内容的确切二进制表示。问题是:

  1. 您使用 ST 填充 usc 联合,但将其作为 char[] 访问,这会产生未定义的行为(但可能适用于所有常见系统)。
  2. 您可能希望以相反的顺序在接收端执行相同的操作。再次使用 UB,但可能有效。
  3. 麻烦来了:您以系统特定格式发送数据,在接收系统上不必相同,对于相同的结构定义。这包括
    • 整数类型的字节顺序(小/大端)
    • 类型的大小,不仅是整数(例如 sizeof(long) 有时在 32 位和 64 位系统之间或在 64 位系统上的不同编译器之间有所不同)
    • 填充字节
    • sizeof(ST) 本身可能存在显着差异

简单地说:不要这样做。如果您仍然使用 boost::serialization,请将其用于整个 ST 结构,而不仅仅是用于其中的字符串。如果您的数据结构变得稍微复杂一些(例如,包含指针、具有重要的构造函数等),无论如何您都必须这样做。

【讨论】:

  • boost::serialization 能保证我避免你描述的麻烦吗?
  • Boost.Serialization 确实是专门为避免这些麻烦而设计的。请参阅list here 中的第 7 条。也就是说,当然,如果您不使用依赖于此类平台特定事物的自定义序列化。
猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 2018-04-30
  • 2020-10-03
  • 2011-10-07
  • 1970-01-01
  • 2015-06-09
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多