您的位置:首页 > 其它

memcpy内存重叠问题

2016-08-06 11:54 267 查看

memcpy内存重叠

之前一直没有注意到内存复制函数的内存重叠问题。今天偶遇遂琢磨了一下,记之。

函数简介:c和c++使用的内存拷贝函数,memcpy函数的功能是从源src所指的内存地址的起始位置开始拷贝n个字节到目标dest所指的内存地址的起始位置中。一般避免内存重叠。

没有内存重叠的情况:

void *mymemcpy(void *dst,const void *src,size_t num)
{
if(NULL == dst || NULL == src){
return NULL;
}
//assert((dst !=NULL) && (src!=NULL));

if(dst>=src+num||src>dst+num){
char * psrc = (char *)src;
char * pdst = (char *)dst;
while(num-->0)*pdst++ = *psrc++;
}
return dst;
}


出现内存重叠的情况

void * mymemcpy(void *dst, const void *src, size_t count)
{
if (dst== NULL || src == NULL)
return NULL;
char *pdest = (char *)(dst);
const char *psrc  = (char *)(psrc);
int n = count;
//pdest地址高于psrc地址,且有重叠
if (pdest > psrc && pdest < psrc+count)
{
for (size_t i=n-1; i != -1; --i)
{
pdest[i] = psrc[i];//从高到低赋值
}
}
//pdest地址低于psrc地址,且有重叠
else if(pdest < psrc && pdest > psrc-count)
{
for (size_t i= 0; i < n; i++)
{
pdest[i] = psrc[i];//从低到高赋值
}
}
return dst;
}


附录:关于memmove,memcpy

1.memmove

函数原型:void *memmove(void *dest, const void *source, size_t count)

返回值说明:返回指向dest的void *指针

参数说明:dest,source分别为目标串和源串的首地址。count为要移动的字符的个数

函数说明:memmove用于从source拷贝count个字符到dest,如果目标区域和源区域有重叠的话,memmove能够保证源串在被覆盖之前将重叠区域的字节拷贝到目标区域中(此时源字符串尾部字符改变)。

2.memcpy

函数原型:void *memcpy(void *dest, const void *source, size_t count);

返回值说明:返回指向dest的void *指针

函数说明:memcpy功能和memmove相同,但是memcpy中dest和source中的区域不能重叠,否则会出现未知结果。

3.两者区别

函数memcpy() 从source 指向的区域向dest指向的区域复制count个字符,如果两数组重叠,不定义该函数的行为。

而memmove(),如果两函数重叠,赋值仍正确进行。

memcpy函数假设要复制的内存区域不存在重叠,如果你能确保你进行复制操作的的内存区域没有任何重叠,可以直接用memcpy;

如果你不能保证是否有重叠,为了确保复制的正确性,你必须用memmove。

memcpy的效率会比memmove高一些,两者的实现:

void* memmove(void* dest, void* source, size_t count)
{
assert((dest!=NULL) && (source !=NULL));
void* ret = dest;
if (dest <= source || dest >= (source + count))
{
while (count --)
*dest++ = *source++;
}
else
{
dest += count - 1;
source += count - 1;
while (count--)
*dest-- = *source--;
}
return ret;
}

void* memcpy(void* dest, void* source, size_t count)
{
assert((dest!=NULL) && (source !=NULL));
void* ret = dest;
while (count--)
*dest++ = *source;
return ret;
}


对于字符串拷贝函数,strcpy()也是存在内存重叠问题的。
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签:  内存重叠