memcpy重叠缓冲区

时间:2014-09-02 18:14:51

标签: c++ c memcpy

使用Aztec线性系统求解器库时,我遇到了奇怪的行为。使用valgrind,我发现这个库在重叠缓冲区上执行memcpy。规范说明memcpy对重叠缓冲区的行为没有定义。

事实证明,许多机器上的memcpy具有与使用for循环执行此操作相同的行为,因此您可以安全地从较高的源复制到较低的目标:

for(int i = 0; i < len; i ++)
  dest[i] = source[i];

但是在我们的大型集群上,重叠缓冲区的memcpy具有不同的行为,从而导致出现问题。

现在我想知道库中的重叠memcpy是正常的还是仅仅是由我的代码中的另一个错误引起的。由于库被广泛使用,我认为应该早先发现memcpy问题。另一方面,绝大多数memcpy实现仍然可能像for循环一样,因此没有人遇到过这个问题。

  • 有人能告诉我他在各种机器上重叠memcpy的经历吗?
  • 我的计算机系统的哪个部分确实提供了memcpy

我想指出的问题是关于各种实现的实践经验,而不是规范所说的内容。

3 个答案:

答案 0 :(得分:13)

我过去曾对此做过一些研究......在Linux上,直到最近,memcpy()的实施工作方式与memmove()类似。重叠内存不是一个问题,根据我的经验,其他UNIX是相同的。根据标准,这并没有改变这是未定义的行为这一事实,你很幸运,在某些平台上它有时会起作用 - memmove()是标准支持的正确答案。

然而,在2010年,glibc维护者推出了一个新的,优化的memcpy(),它改变了memcpy()对于某些英特尔核心类型的行为,其中C标准库编译得更快,但没有较长的作品如memmove() [1]。 (我似乎还记得,这是仅针对大于80字节的内存段触发的新代码)。有趣的是,这导致了像Adobe的Flash版本的Linux版本[2]以及其他几个开源软件包(早在2010年Fedora Linux成为第一个采用更改后的{{1}在glibc)。

答案 1 :(得分:12)

memcpy()不支持重叠内存。这允许在缓冲区重叠时不起作用的优化。

然而,没有什么可以真正研究的,因为C提供了 支持重叠内存的替代方案:memmove()。其用法与memcpy()相同。如果区域可能重叠,您应该使用它,因为它可以解释这种可能性。

答案 2 :(得分:0)

memmove()可用于此目的。 memcpy() [man-page]的定义条件为&#34; source&#34;不应与目的地重叠。

为了更好地理解,您可以尝试通过尝试定义其版本来了解memcpy()memmove()。 [more info]