如何实现支持重叠区域的内存移动(memmove),现有代码错误如何排查?
内存移动(memmove)功能实现问题修复
原有代码存在的问题
- 非法使用字符串终止符
\0作为内存拷贝结束判断:内存块中可能包含数值为0的字节,且你需要拷贝固定size长度的内存,而非仅拷贝到字符串末尾,该判断逻辑完全不符合需求。 - 临时缓冲数组逻辑错误:第一遍拷贝结束后指针
b已经指向缓冲数组末尾,第二遍拷贝时读取的是缓冲数组外的非法内存数据,完全无法得到正确结果。 - 变长数组
char buff[size]存在安全风险:该写法属于C99可选特性兼容性差,且size过大时会直接触发栈溢出,使用临时缓冲的实现方案本身性能和可靠性都极低。 - 未规范实现主函数:
void main()不是C标准规定的主函数写法,标准实现应为int main(void)。
正确实现方案
不需要额外开辟缓冲,只需要根据源地址和目标地址的相对位置选择拷贝方向,即可完美处理重叠场景,代码如下:
#include <stdio.h> void mem_move(void* dest, const void* src, unsigned size) { // 转成char*按字节操作 char* d = (char*)dest; const char* s = (const char*)src; if (d > s && d < s + size) { // 目标地址在源地址中间的重叠场景,从后往前拷贝 d += size - 1; s += size - 1; while (size--) { *d-- = *s--; } } else { // 无重叠或者目标在源前面,正常从前往后拷贝 while (size--) { *d++ = *s++; } } } int main(void) { char buffer[] = "one two three "; // 测试目标地址在源地址后面的重叠场景 mem_move(buffer + 3, buffer, 10); printf("测试1结果:%s\n", buffer); char buffer2[] = "one two three "; // 测试源地址在目标地址后面的重叠场景 mem_move(buffer2, buffer2 + 3, 10); printf("测试2结果:%s\n", buffer2); return 0; }
实现说明
- 当目标地址位于源地址的内存区间内部时,从头部开始拷贝会覆盖还未读取的源数据,因此改为从尾部倒序拷贝即可避免该问题。
- 不需要额外开辟内存空间,兼容性和性能都远优于临时缓冲方案。
- 源指针加
const修饰符合常量正确性要求,避免误修改源数据。
内容的提问来源于stack exchange,提问作者Pen4o
相关产品推荐
相关产品推荐

