内存重叠以及memcpy和memmove函数详解

内存重叠

当我们进行内存拷贝(memcpy函数)时或者在自己实现内存拷贝函数strcpy时,如果存在目标地址在原地址的范围内就造成了内存重叠。一开始看到这个名词的时候,确实有点难以理解,经过学习,我利用以下的例子来说明内存重叠问题。

首先,先介绍一下memcpy和memmove函数

memcpy和memmove函数

void *memcpy( void *dest, const void *src, size_t count );
void *memmove( void* dest, const void* src, size_t count );
  • memcpy和memmove函数都是用于从src拷贝count个字节到dest。
  • 但是,如果目标区域和源区域有重叠的话: memcpy不能够确保源串所在重叠区域在拷贝之前被覆盖,并且memcpy会出现错误。memmove能够保证源串在被覆盖之前将重叠区域的字节拷贝到目标区域中,复制后src内容会被更改, 当目标区域与源区域没有重叠则和memcpy函数功能相同。

memmove的处理措施:

(1)当源内存的首地址等于目标内存的首地址时,不进行任何拷贝。
(2)当源内存的首地址大于目标内存的首地址时,实行正向拷贝。
(3)当源内存的首地址小于目标内存的首地址时,实行反向拷贝。

接下来,借助于memcpy函数来说明内存重叠

memcpy(void *dest, void *src, size_t num)是将src指向的地址中的num个字节拷贝到dest目标地址中。假设我们需要拷贝六个字节到dest内存地址中,根据dest和src的关系,内存拷贝可以分为以下三类:

情况一:

目标地址与源地址没有任何重叠,即dest 地址> src地址 + 6或者dest 地址< src地址 - 6:
在这里插入图片描述
在这里插入图片描述

  • 这时,不会造成内存重叠,直接从左到右进行拷贝即可

情况二:

src地址 - 6< dest 地址< src地址:
在这里插入图片描述
这时即使会覆盖掉src的部分内存,但是并不会造成内存重叠。

情况三:

目标地址dest位于原地址的内存范围之内,即src 地址< dest 地址< src地址 + 6,这时进行内存拷贝,情况如下:
在这里插入图片描述
此时如果对src进行从左到右的内存拷贝,当该拷贝4的时候,此时原先src部分4的内存已经被1给覆盖掉了,就产生了拷贝错误。

解决:

  • 如果存在内存重叠,就从高地址进行拷贝
  • 自己实现的memcpy如下:
char *my_memcpy(char *dst, const char* src, int cnt)
{
	 assert(dst != NULL && src != NULL);
	 char *ret = dst;
	 /*内存᯿叠,从⾼地址开始复制*/
	 if (dst >= src && dst <= src+cnt-1)
	 {
		 dst = dst+cnt-1;
		 src = src+cnt-1;
		 while (cnt--)
		 {
			 *dst-- = *src--;
		 }
	 } 
	 else //正常情况,从低地址开始复制
	 {
		  while (cnt--)
		 {
			 *dst++ = *src++;
		 }
     }
	 return ret;
}
  • 8
    点赞
  • 5
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值