【问题标题】:Safe use of memcpy on overlapping region [duplicate]在重叠区域上安全使用 memcpy [重复]
【发布时间】:2014-01-18 13:42:55
【问题描述】:

在以下场景中使用memcpy 是否安全,其中将数据从较大的索引复制到同一块中的较小索引的块中。例如:

char buf[100];
// fill in the data ...
memcpy(&buf[10], &buf[15], 10);

在上述情况下,我不关心位置 10 - 19 的数据,如果它被覆盖就可以了。有什么理由应该避免这种情况并改用memmove吗?

编辑:抱歉,我没有正确传达我的意图,所以假设我有来自索引 10 - 19 的数据和来自索引 15 - 24 的数据,我想从 15 - 24 复制 10 - 19 的数据,但我没有不关心 10 到 19 的数据,即使它们重叠,对我们 memcpy 是否安全?

【问题讨论】:

  • 不会重叠 - memcpy(&buf[20], &buf[10], 20);
  • 对不起,我的意思是反过来,把它固定在上面。
  • 如果A和B不重叠,那么B和A也不重叠...
  • 如果有重叠,memcpy()s 的行为是未定义的。对于 memmove(),可以保证正确的行为。
  • @wildplasser 是不是因为没有定义每个字节的复制顺序?

标签: c memcpy memmove


【解决方案1】:

编辑:

根据您的编辑,反转以下答案,因为现在您不同意 restrict 约束。


旧答案

是的,它是安全的。您正在将buf[10]buf[19] 复制到buf[20]buf[29]。 (注意memcpy 的第一个参数是目的地。所以buf[10]buf[19]不会被覆盖。)

memcpy 在 C11 中定义为:

void *memcpy(void * restrict s1, const void * restrict s2, size_t n);

注意restrict 关键字。 C11 在 6.7.3.8 说(强调我的):

通过限制限定指针访问的对象具有特殊关联 用那个指针。这种关联,在下面的 6.7.3.1 中定义,要求所有访问 该对象直接或间接使用该特定指针的值.135) 预期 使用限制限定符(如寄存器存储类)是为了提升 优化,并从所有预处理翻译中删除限定符的所有实例 组成符合程序的单元不会改变其含义(即,可观察的 行为)。

在您的示例中,buf[10]buf[19] 只能通过 s2 指针访问,buf[20]buf[29] 只能通过 s1 指针访问。因此,您对memcpy 的使用是完全可以的。

简单来说,只要您提供给memcpy 的数组不重叠,就可以。

【讨论】:

  • 抱歉看到上面的编辑,如果我不关心重叠区域中的早期数据并用后来的数据覆盖它是否安全?
  • 如果区域重叠,是否不安全,因为无法保证复制数据的顺序?如果索引 j (j > i && j
  • @user689046,无法保证数据将从哪个方向复制,因此您可能会得到完全损坏的数据。这就是 memmove 存在的原因。
  • 谢谢你为我澄清了事情。
  • 如果不可能在读取之前写入,是否会使用一个限制指针读取一个值,然后使用另一个调用 UB 写入该值[例如代码*p=*q; 与 p 和 q 相等]?在某些情况下,将memcpy(p,p,n); 定义为以任意顺序将任何或所有值复制到自身,这将比将其视为未定义行为更有效地编写代码。
【解决方案2】:

正如您在声明中指定的那样:

memcpy(&buf[20], &buf[10], 10);

索引1019 的数据与索引2029 的数据不重叠,因此即使您关心索引@987654327 中的数据,使用memcpy() 也是安全的@到19

请注意,如果数据重叠,即使您不关心要复制的数据,使用 memcpy 也不安全,因为未指定 memcpy 的复制方向

【讨论】:

  • 抱歉我把destination和src搞混了,在上面修好了!
  • 感谢未定义副本的顺序为我清除了它。
【解决方案3】:

这是安全的。没有理由使用memmove.

memcpy 没有指定方向,所以memcpy(&buf[20], &buf[10], 20); 会令人困惑。我们必须确保副本从&buf[20] 开始。 memmovestd::copy 确实做出了这样的保证,因此在这种情况下可以安全地使用它们。

memcpy(&buf[10], &buf[20], 10); 不会重叠,因为&buf[10] + 9 == &buf[19] 是复制到的生成地址,并且小于&buf[20]

【讨论】:

  • 你说它不安全然后你说数据不重叠。你的答案令人困惑!
  • @EricPostpischil 嗯,好的——我用问号回答了这个问题。容易固定。
猜你喜欢
  • 2014-10-27
  • 1970-01-01
  • 2020-11-25
  • 1970-01-01
  • 1970-01-01
  • 2014-03-23
  • 2013-04-05
  • 1970-01-01
  • 2011-09-19
相关资源
最近更新 更多