从lftp的源码看memmove和memcpy的区别

区别很简单,看这两个函数的man手册就能看的出来。简单来说,memmove是把一堆byte从src移到dst,memcpy是把一堆byte从 src拷贝到dst,最大不同的是:memmove是先把一堆byte拷贝到一个临时的array中,然后再把这个临时的array写到dst中去;而 memcpy没有这个逻辑,直接就是从src一个一个字节的读,同时往dst一个一个字节的写。这样就导致了一个最根本的不同:

memcpy不适合或者说不能处理src和dst两块内存有重叠(overlap)的情况。因为memcpy是直接从src拷贝,然后往dst中写,这样,如果src和dst两块内存有重叠,这样就会导致写数据出错了。比如:

Code: Select all
src.........\0
   dst.........\0


这样的情况,由于dst和src有重叠的部分,这样,在写dst的时候,同时就把src中的内容也改写了,这样拷贝出来的东西就不对了。

这就是两者的区别。下面给出一段代码来更明确的显式这两个函数的用法。代码来自lftp的源代码,我也是看了这段源代码才知道这两个函数有这样大的区别的。

Code: Select all
/*
* replace string mem by string s, len is the length of string s
* NOTE: use memmove while mem & s has overlaps and use
* memcpy while they have no overlaps
*/
char *xstrset(char *&mem,const char *s,size_t len)
{
   if(!s)
   {
      xfree(mem);
      return mem=0;
   }
#ifdef MEM_DEBUG
   printf("xstrset \"%.*s\"\n",len,s);
#endif
   if(s==mem)
   {
      mem[len]=0;
      return mem;
   }
   size_t old_len=(mem?strlen(mem)+1:0);
   // s & mem have overlaps
   // and s's start point is in mem's range
   // so use memmove, cannot use memcpy
   // mem.........\0
   //       s..............\0
   // after memmove
   // mem..............\0  -- mem has new contents(s)
   if(mem && s>mem && s<mem+old_len)
   {
      memmove(mem,s,len);
      mem[len]=0;
      return mem;
   }

   // mem & s have no overlaps and the mem is too small
   // mem cannot accommodate the whole `s' so realloc the memory
   if(old_len<len+1)
      mem=(char*)xrealloc(mem,len+1);
   memcpy(mem,s,len);
   mem[len]=0;
   return mem;
}


这段代码是一个复制s到mem中的function,s和mem都表示string,len是s这个string的长度。函数中的 xmalloc, xfree就相当于malloc和free,只不过做了一些封装,加了一个计数器进去用来追踪申请和释放的次数而已。关键的就是看这个函数中的几个if判 断,这些if判断就是判断mem和s两者有没有重叠的部分,从而调用不同的函数。
posted @ 2011-03-26 10:25  super119  阅读(625)  评论(1编辑  收藏  举报