C++ 重叠缓冲区的memcpy
使用Aztec线性系统解算器库时,我遇到了奇怪的行为。使用valgrind,我发现这个库对重叠的缓冲区执行C++ 重叠缓冲区的memcpy,c++,c,memcpy,C++,C,Memcpy,使用Aztec线性系统解算器库时,我遇到了奇怪的行为。使用valgrind,我发现这个库对重叠的缓冲区执行memcpy。规范指出,memcpy在重叠缓冲区上的行为未定义 事实证明,许多机器上的memcpy具有与使用for循环相同的行为,因此可以安全地从较高的源复制到较低的目标: for(int i = 0; i < len; i ++) dest[i] = source[i]; for(int i=0;i
memcpy
。规范指出,memcpy
在重叠缓冲区上的行为未定义
事实证明,许多机器上的memcpy
具有与使用for循环相同的行为,因此可以安全地从较高的源复制到较低的目标:
for(int i = 0; i < len; i ++)
dest[i] = source[i];
for(int i=0;i
但是在我们的大型集群上,重叠缓冲区的memcpy
有不同的行为,这会导致问题
现在我想知道库中的重叠memcpy
是正常的还是我的代码中的另一个bug造成的。由于该库被广泛使用,我假设memcpy
问题应该更早发现。另一方面,仍有可能绝大多数memcpy
实现的行为类似于for循环,因此没有人遇到过这个问题
- 有人能告诉我他在各种机器上使用重叠
的经验吗memcpy
- 我的计算机系统的哪个部分实际上提供了
memcpy
memcpy()
不支持重叠内存。这允许在缓冲区重叠的情况下进行不起作用的优化
但是,没有太多需要研究的内容,因为C提供了一种支持重叠内存的替代方法:
memmove()
。它的用法与memcpy()
相同。如果区域可能重叠,您应该使用它,因为它说明了这种可能性。我过去对此做过一些研究。。。在Linux上,直到最近,memcpy()
的实现方式与memmove()
非常相似,重叠内存不是问题,根据我的经验,其他unix也是一样的。这并没有改变这样一个事实,即根据标准,这是一种未定义的行为,幸运的是,在某些平台上,它有时可以工作,memmove()
是标准支持的正确答案
然而,在2010年,glibc维护人员推出了一种新的优化的memcpy()
,它改变了memcpy()
对于某些英特尔核心类型的行为,其中C标准库的编译速度更快,但不再像memmove()
[1]那样工作。(我似乎还记得,这是仅针对大于80字节的内存段触发的新代码)。有趣的是,这导致Adobe Flash player的Linux版本以及其他几个开源软件包(早在2010年,Fedora Linux成为第一个在glibc中采用经过更改的memcpy()
的软件包)都崩溃了[2]
- [1]
- [2]
memmove()
可用于此目的memcpy()
[]的定义条件是“源”不应与目标重叠
为了更好地理解,您可以尝试通过定义您的版本来理解
memcpy()
和memmove()
。[]规范对此很清楚。但是我想知道库是否经常执行这样的memcpy
,而且没有人遇到过这个问题,因为绝大多数实现的行为都像for循环,或者我只是假设驱动库的代码中有一个bug。如果你发现库发出这样的调用,那就是1)库本身有一个bug,或者2)库如何使用的错误,导致不应该重叠的内存无法使用。但是,在某些情况下它确实有效,这并不意味着它不是一个bug。请提供一个最小的示例,以便我们能够重现您的问题,并让您知道bug是否在库中或代码中。我从未了解memcpy的这个问题。当然,这只是一个比较,以确定您是否需要从源缓冲区的顶部或底部进行复制?@Martin James很久以前和很久以前,大量使用的memcpy()
的优先级迫使它非常精简。按照当时的标准,“一个比较”是臃肿的软件,通常不需要——而且它阻止了某些优化。它只是减慢了系统的速度。因此诞生了memmove()
@chux orite,谢谢:)这正是我想要的答案。因此,这种行为很有可能在该库中存在多年,从未引起问题……完全正确。当我将旧代码移动到带有新更改的新服务器时,我被它咬了一口。