首页
学习
活动
专区
圈层
工具
发布
社区首页 >问答首页 >它是普通的memcpy覆盖它刚刚写的数据吗?

它是普通的memcpy覆盖它刚刚写的数据吗?
EN

Stack Overflow用户
提问于 2022-02-23 04:42:53
回答 2查看 177关注 0票数 0

我使用memcpy()将数据写入设备,使用逻辑分析器/PCIe分析器,我可以看到实际的存储。

我的设备得到的商店比预期的多。

例如,

代码语言:javascript
复制
auto *data = new uint8_t[1024]();
for (int i=0; i<50; i++){
  memcpy((void *)(addr), data, i);
}

对于i=9,我看到这些商店:

从字节0到3的7

  • 3B

  • 4B,从字节4到

  • 4b,仅从字节5到7 ,重写相同的数据->效率低且无用的store

  • 1B字节8

最后,所有的9位字节都被写入了,但是memcpy创建了一个额外的3B重写存储,它已经写了什么,而没有更多了。

是预期的行为吗?问题是对于C和C++来说,我有兴趣知道为什么会发生这种情况,它看起来效率很低。

EN

回答 2

Stack Overflow用户

发布于 2022-02-23 07:16:51

以下说明了为什么memcpy可以以这种方式实现。

要复制9个字节,从4字节对齐地址开始,memcpy发出以下指令(描述为伪代码):

destination+0.

  • Load

  • 从source+0加载4个字节,将4个字节存储到source+4,4个字节存储到destination+4.

  • Load,4个字节从source+5存储到destination+5.

,4个字节存储到destination+5.

处理器通过硬件中的这些数据传输实现存储指令:

由于对齐了对齐了对齐的destination+0.

  • Since

  • ,所以存储4字节到destination+8.

destination+4是对齐的,存储4字节到destination+4.

  • Since destination+5没有对齐,存储3字节到destination+3,存储1字节到destination+8.

这是一种简单而高效的编写memcpy的方法。

如果长度小于4个字节,则跳到相应的单独代码。destination+length−4.

  • 循环复制4个字节,直到只剩下4个字节。如果长度不是4个字节的倍数,则将4个字节从source+length−4复制到

复制最后几个字节的单个步骤可能比在三个不同情况下进行不同情况的分支更有效。

票数 1
EN

Stack Overflow用户

发布于 2022-02-23 08:59:56

是预期的行为吗?

预期的行为是它可以做它想做的任何事情(包括在结束后写入,特别是以“将8个字节读入寄存器,修改寄存器中的第一个字节,然后写8个字节”的方式),只要结果像遵循C抽象机器的规则一样工作。

使用逻辑分析器/PCIe分析器查看实际存储远远超出了“工作就像遵循抽象机器的规则”的范围,因此没有任何期望是不合理的。

具体来说,您不能假设写入将以任何特定的顺序进行,不能假设任何与任何单个写入的大小有关的内容,不能假设写入不会重叠,不能假设写入不会超过区域的末尾,不能假设写操作实际上会发生(没有volatile),甚至不能假设CHAR_BIT不大于8(或者memcpy(dest, source, 10);不要求写入20位数/“8位字节”)。

如果您需要有关写的保证,那么您需要自己执行这些保证(例如,可能创建一个volatile字段的结构,以强制编译器确保写入按特定的顺序进行,也可能使用带显式栅栏/障碍的内联程序集,等等)。

票数 1
EN
页面原文内容由Stack Overflow提供。腾讯云小微IT领域专用引擎提供翻译支持
原文链接:

https://stackoverflow.com/questions/71231476

复制
相关文章

相似问题

领券
问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档