You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

寻求无大临时缓冲区的memmove2实现方案及问题命名

多源重叠内存复制函数memmove2的实现问题

函数需求

需要实现如下签名的函数:

void *memmove2 ( void *destination, const void *source1, size_t num1, const void *source2, size_t num2 );

该函数需连续将source1的num1字节、source2的num2字节复制到destination中,且所有参数对应的内存区域可任意重叠(目标与任一源、源之间或三者均重叠),所有复制操作必须基于内存的初始状态执行。

示例场景

char test[10] = "123456789";
memmove2(test, test + 1, 3, test + 2, 4);

执行后应得到结果"234345689"(前3字节来自初始的test+1,后4字节来自初始的test+2)。

错误方案:连续调用memmove

如果连续调用标准memmove无法达成目标:

char test[10] = "123456789";
memmove(test, test + 1, 3);
memmove(test + 3, test + 2, 4);

执行后会得到"234445689"——因为第一次memmove会修改test[0]-test[2],导致第二次memmove读取的test+2已经是被修改后的值,而非初始状态。

简单可靠方案:大缓冲区中转

最直接的实现是用与总复制字节数(num1+num2)等大的临时缓冲区,先将两个源的初始数据复制到缓冲区,再统一复制到目标:

char test[10] = "123456789";
char temp[7];
memcpy(temp, test + 1, 3);
memcpy(temp + 3, test + 2, 4);
memcpy(test, temp, 7);

核心问题与解答

是否存在无需等大缓冲区的通用方案?

无缓冲区(完全原地操作):不可能实现

因为存在无法避免的冲突场景:当目标区域会覆盖后续需要读取的源数据时,原地复制会提前修改源数据,导致无法获取初始状态的字节。比如前面的示例,若不保存初始的test+2区域,第一次复制source1到目标后,test[2]会被修改为初始的test[3],后续读取source2的test[2]时就不是初始值了,必然得到错误结果。

小缓冲区(小于总复制字节数):可行但复杂度极高

可以通过内存区域重叠分析,仅保存那些会被目标提前覆盖的源字节,用更小的缓冲区完成复制,步骤大致如下:

  1. 分析目标区域(destination到destination+num1+num2-1)与两个源区域的重叠关系,找出所有会被目标覆盖的源字节(这些字节必须在被覆盖前保存)。
  2. 将这些需要保护的字节复制到小缓冲区。
  3. 先复制不会被覆盖的源区域到目标。
  4. 最后从缓冲区复制被保护的源字节到目标对应位置。

但这种方案需要处理所有可能的重叠组合(目标与src1重叠、目标与src2重叠、src1与src2重叠、三者均重叠等),实现复杂度极高;且在最坏场景下(所有源字节都会被目标覆盖),仍需与总复制字节数等大的缓冲区,无法完全避免内存占用。

该问题的命名

这个问题属于多源重叠内存复制(Multi-source overlapping memory copy),也可称为合并式重叠内存迁移,是系统编程中复杂内存重叠操作的一类场景。

工程选择

虽然小缓冲区方案在部分场景下能减少内存占用,但大缓冲区方案实现简单、逻辑清晰、可靠性高,是工程实践中的首选方案。

内容的提问来源于stack exchange,提问作者FrederikVds

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.07.01 04:34:59