【问题标题】:Is it safe to copy the bytes of an object out to an array and back again将对象的字节复制到数组并再次返回是否安全
【发布时间】:2020-01-22 05:07:46
【问题描述】:

将对象的字节复制到unsigned char 的数组中然后使用memcpy 再次复制回来是否安全,是否保持对象不变?

也就是说,对于任何t,以下安全:

template <typename T>
void copy_back_and_forth(T& t) {
  unsigned char buf[sizeof(T)];
  std::memcpy(buf, &t, sizeof(T));
  std::memcpy(&t, buf, sizeof(T));
}

...t 是否保持不变?

【问题讨论】:

  • 是的............
  • unsigned charstd::byte 的任何附件?
  • @Tas - 嗯,是的,如果他们之间的答案会有所不同,我当然很感兴趣。
  • @sshashank124 - 这对你来说可能很明显,但是对于例如cppreference 当然没有说清楚:他们说 If the objects are potentially-overlapping or not TriviallyCopyable, the behavior of memcpy is not specified and may be undefined. ... 并链接回 SO。
  • 抱歉,这听起来并不居高临下。只是想满足最小字符要求。是的,应该是一样的。查看您分配单独缓冲区的具体情况,它应该可以正常工作

标签: c++ language-lawyer


【解决方案1】:

如果T 是普通可复制类型,并且t 不是潜在重叠的子对象,则t 的值保证不变。最新草案的标准报价:

[基本类型]

对于任何对象(除了可能重叠的子对象) 普通可复制类型 T,无论对象是否持有有效的 类型 T 的值,构成 可以将对象复制到 char、unsigned char 或 std​::​byte ([cstddef.syn]).37 如果复制了该数组的内容 回到对象中,对象随后应保持其原始 价值。

37) 例如,通过使用库函数([headers])std​::​memcpy 或 std​::​memmove。

事实上,该标准有一个几乎相同的例子:

[示例:

constexpr std::size_t N = sizeof(T);
char buf[N];
T obj;                          // obj initialized to its original value
std::memcpy(buf, &obj, N);      // between these two calls to std​::​memcpy, obj might be modified
std::memcpy(&obj, buf, N);      // at this point, each subobject of obj of scalar type holds its original value

—结束示例]

【讨论】:

  • 对,这是memcpy 安全的一般条件,即使在调用之间修改了对象。我对调用背靠背的特殊情况感兴趣,想知道这是否会放松条件。特别是,虽然与标准的完全一样看起来非常相似,但注释“obj可能会被修改”非常相关。
  • @BeeOnRope 同样相关的是“在这些调用之间”。在第二次 memcpy 之后,保证该对象已被修改回原始值。我想这意味着不能保证该操作是线程安全的。
猜你喜欢
  • 2013-10-14
  • 2011-08-03
  • 2011-06-23
  • 2011-04-03
  • 2013-08-04
  • 1970-01-01
  • 2010-11-11
  • 2015-09-02
  • 2011-12-10
相关资源
最近更新 更多