我使用memcpy()将数据写入设备,使用逻辑分析器/PCIe分析器,我可以看到实际的存储。
我的设备得到的商店比预期的多。
例如,
auto *data = new uint8_t[1024]();
for (int i=0; i<50; i++){
memcpy((void *)(addr), data, i);
}对于i=9,我看到这些商店:
从字节0到3的7
。
最后,所有的9位字节都被写入了,但是memcpy创建了一个额外的3B重写存储,它已经写了什么,而没有更多了。
是预期的行为吗?问题是对于C和C++来说,我有兴趣知道为什么会发生这种情况,它看起来效率很低。
发布于 2022-02-23 07:16:51
以下说明了为什么memcpy可以以这种方式实现。
要复制9个字节,从4字节对齐地址开始,memcpy发出以下指令(描述为伪代码):
destination+0.
,4个字节存储到destination+5.
处理器通过硬件中的这些数据传输实现存储指令:
由于对齐了对齐了对齐的destination+0.
destination+4是对齐的,存储4字节到destination+4.
这是一种简单而高效的编写memcpy的方法。
如果长度小于4个字节,则跳到相应的单独代码。destination+length−4.
复制最后几个字节的单个步骤可能比在三个不同情况下进行不同情况的分支更有效。
发布于 2022-02-23 08:59:56
是预期的行为吗?
预期的行为是它可以做它想做的任何事情(包括在结束后写入,特别是以“将8个字节读入寄存器,修改寄存器中的第一个字节,然后写8个字节”的方式),只要结果像遵循C抽象机器的规则一样工作。
使用逻辑分析器/PCIe分析器查看实际存储远远超出了“工作就像遵循抽象机器的规则”的范围,因此没有任何期望是不合理的。
具体来说,您不能假设写入将以任何特定的顺序进行,不能假设任何与任何单个写入的大小有关的内容,不能假设写入不会重叠,不能假设写入不会超过区域的末尾,不能假设写操作实际上会发生(没有volatile),甚至不能假设CHAR_BIT不大于8(或者memcpy(dest, source, 10);不要求写入20位数/“8位字节”)。
如果您需要有关写的保证,那么您需要自己执行这些保证(例如,可能创建一个volatile字段的结构,以强制编译器确保写入按特定的顺序进行,也可能使用带显式栅栏/障碍的内联程序集,等等)。
https://stackoverflow.com/questions/71231476
复制相似问题