同一内存区域的const与非const指针及memmove重叠区域疑问
关于SPI_TransmitReceive函数重叠缓冲区调用的疑问
问题描述
我写了这么一个函数:
void SPI_TransmitReceive(const uint8_t* txbuf, uint8_t* rxbuf, size_t size);
调用的时候把同一个缓冲区同时传给txbuf和rxbuf:
uint8_t mybuf[200]; SPI_TransmitReceive(mybuf, mybuf, 200);
这么做会触发未定义行为吗?
补充说明
假设这个函数的实现是这样的:
void SPI_TransmitReceive(const uint8_t* txbuf, uint8_t* rxbuf, size_t size) { std::memmove(rxbuf, txbuf, size); }
我看到cppreference上说memmove如果遇到内存区域重叠会导致未定义行为,这是不是笔误?
解答
首先要纠正一个关键误解:你搞反了memmove和memcpy的特性。
memcpy才是当源和目标内存区域重叠时行为未定义;memmove恰恰是专门为处理重叠内存区域设计的,它会先把需要复制的数据临时存起来,再写入目标地址,所以哪怕源和目标完全重叠,也能保证操作安全,不存在未定义行为。你看到的cppreference描述大概率是把两个函数搞混了,或者是你看错了函数名。
再回到你的函数调用问题:
- 如果是你补充的这种用
memmove实现的函数:把同一个缓冲区传进去完全没问题,不会触发未定义行为,最终缓冲区内容和原内容一致(因为自己复制自己)。 - 如果这个函数是实际操作SPI硬件的收发逻辑(这才是这类函数的真实用途):SPI是同步收发,每发送一个字节的同时会接收一个字节。此时用同一个缓冲区的话,每一步接收的新字节会覆盖掉还没发送的原字节,最终缓冲区的内容会是混乱的,但这属于逻辑错误,不是C标准定义的未定义行为。
内容的提问来源于stack exchange,提问作者Xeenych Xeenych
相关产品推荐
相关产品推荐

