内存重叠strcpy\memcpy

时间:2023-01-20 16:55:45

1.strcpy函数

详细参考:http://www.cnblogs.com/chenyg32/p/3739564.html

详细参考:http://blog.chinaunix.net/uid-26495963-id-3080058.html

已知strcpy函数的原型是:

char *strcpy(char *dst, const char *src);
实现strcpy函数
解释为什么要返回char *
假如考虑dst和src内存重叠的情况,strcpy该怎么实现

 2.strcpy函数的形式

char *strcpy(char *strDest, const char *strSrc) 
{ 
    assert((strDest!=NULL) && (strSrc !=NULL)); 
    char *address = strDest;  
    while( (*strDest++ = * strSrc++) != '\0')  
          
    return address ;  
} 

3.memcpy函数的微软实现

 void * __cdecl memcpy (void * dst,const void * src, size_t count )  
 {  
     void * ret = dst;  
#if defined (_M_MRX000) || defined (_M_ALPHA) || defined (_M_PPC)           
     {          
         extern void RtlMoveMemory( void *, const void *, size_t count ); 
         RtlMoveMemory( dst, src, count ); 
     }  
#else  /* defined (_M_MRX000) || defined (_M_ALPHA) || defined (_M_PPC) */           
     /*          * copy from lower addresses to higher addresses          */         
     while (count--) {  
         *(char *)dst = *(char *)src; 
         dst = (char *)dst + 1;  
         src = (char *)src + 1; 
     }  
#endif  /* defined (_M_MRX000) || defined (_M_ALPHA) || defined (_M_PPC) */          
     return(ret); 
 }  

4.memmove函数用法和实现

void *memmove(void *dest, const void *source, size_t count)
 {
  assert((NULL != dest) && (NULL != source));
  char *tmp_source, *tmp_dest;
  tmp_source = (char *)source;
  tmp_dest = (char *)dest;

  if(tmp_source<=tmp_dest&&tmp_source+count>=tmp_dest)
  {
   tmp_source += count - 1;
   tmp_dest += count - 1;
   while(count--)
    *tmp_dest-- = *tmp_source--;
  }
  else
  {
   while (count--)
   {
    *tmp_dest++=*tmp_source++;
   }
  }
 
  return tmp_dest;
 }

4. 举例解释上边几个函数的不同

 dst>=src

 内存重叠strcpy\memcpy

src+cnt>=dst

内存重叠strcpy\memcpy

第一种情况下,拷贝重叠的区域不会出现问题,内容均可以正确的被拷贝。
第二种情况下,问题出现在
右边的两个字节,这两个字节的原来的内容首先就被覆盖了而且没有保存。所以接下来拷贝的时候,拷贝的是已经被覆盖的内容,显然这是有问题的。

 举例

#include <iostream>
#include <stdio.h>

int main(void)
{
char s[]="123456789";
char d[]="123";
strcpy(d,s);
printf("%s,\n%s",d,s);
return 0
}

key :以上程序的结果为:123456789,56789

cause:至于原因,应该是当初分配的内存地址是连续内存的问题,原来是1234\0123456789\0,strcpy后变成了123456789\06789\0