I am trying to understand the difference between memcpy() and memmove(), and I have read the text that memcpy() doesn't take care of the overlapping source and destination whereas memmove() does.

However, when I execute these two functions on overlapping memory blocks, they both give the same result. For instance, take the following MSDN example on the memmove() help page:-

Is there a better example to understand the drawbacks of memcpy and how memmove solves it?

// crt_memcpy.c // Illustrate overlapping copy: memmove always handles it correctly; memcpy may handle // it correctly. #include <memory.h> #include <string.h> #include <stdio.h> char str1[7] = "aabbcc"; int main( void ) { printf( "The string: %s\n", str1 ); memcpy( str1 + 2, str1, 4 ); printf( "New string: %s\n", str1 ); strcpy_s( str1, sizeof(str1), "aabbcc" ); // reset string printf( "The string: %s\n", str1 ); memmove( str1 + 2, str1, 4 ); printf( "New string: %s\n", str1 ); } 

Output:

The string: aabbcc New string: aaaabb The string: aabbcc New string: aaaabb 
7

11 Answers

I'm not entirely surprised that your example exhibits no strange behaviour. Try copying str1 to str1+2 instead and see what happens then. (May not actually make a difference, depends on compiler/libraries.)

In general, memcpy is implemented in a simple (but fast) manner. Simplistically, it just loops over the data (in order), copying from one location to the other. This can result in the source being overwritten while it's being read.

Memmove does more work to ensure it handles the overlap correctly.

EDIT:

(Unfortunately, I can't find decent examples, but these will do). Contrast the memcpy and memmove implementations shown here. memcpy just loops, while memmove performs a test to determine which direction to loop in to avoid corrupting the data. These implementations are rather simple. Most high-performance implementations are more complicated (involving copying word-size blocks at a time rather than bytes).

5

The memory in memcpy cannot overlap or you risk undefined behaviour, while the memory in memmove can overlap.

char a[16]; char b[16]; memcpy(a,b,16); // valid memmove(a,b,16); // Also valid, but slower than memcpy. memcpy(&a[0], &a[1],10); // Not valid since it overlaps. memmove(&a[0], &a[1],10); // valid. 

Some implementations of memcpy might still work for overlapping inputs but you cannot count of that behaviour. While memmove must allow for overlapping.

1

Just because memcpy doesn't have to deal with overlapping regions, doesn't mean it doesn't deal with them correctly. The call with overlapping regions produces undefined behavior. Undefined behavior can work entirely as you expect on one platform; that doesn't mean it's correct or valid.

1

Both memcpy and memove do similar things.

But to sight out one difference:

#include <memory.h> #include <string.h> #include <stdio.h> char str1[7] = "abcdef"; int main() { printf( "The string: %s\n", str1 ); memcpy( (str1+6), str1, 10 ); printf( "New string: %s\n", str1 ); strcpy_s( str1, sizeof(str1), "aabbcc" ); // reset string printf("\nstr1: %s\n", str1); printf( "The string: %s\n", str1 ); memmove( (str1+6), str1, 10 ); printf( "New string: %s\n", str1 ); } 

gives:

The string: abcdef New string: abcdefabcdefabcd The string: abcdef New string: abcdefabcdef 
1

Your demo didn't expose memcpy drawbacks because of "bad" compiler, it does you a favor in Debug version. A release version, however, gives you the same output, but because of optimization.

 memcpy(str1 + 2, str1, 4); 00241013 mov eax,dword ptr [str1 (243018h)] // load 4 bytes from source string printf("New string: %s\n", str1); 00241018 push offset str1 (243018h) 0024101D push offset string "New string: %s\n" (242104h) 00241022 mov dword ptr [str1+2 (24301Ah)],eax // put 4 bytes to destination 00241027 call esi 

The register %eax here plays as a temporary storage, which "elegantly" fixes overlap issue.

The drawback emerges when copying 6 bytes, well, at least part of it.

char str1[9] = "aabbccdd"; int main( void ) { printf("The string: %s\n", str1); memcpy(str1 + 2, str1, 6); printf("New string: %s\n", str1); strcpy_s(str1, sizeof(str1), "aabbccdd"); // reset string printf("The string: %s\n", str1); memmove(str1 + 2, str1, 6); printf("New string: %s\n", str1); } 

Output:

The string: aabbccdd New string: aaaabbbb The string: aabbccdd New string: aaaabbcc 

Looks weird, it's caused by optimization, too.

 memcpy(str1 + 2, str1, 6); 00341013 mov eax,dword ptr [str1 (343018h)] 00341018 mov dword ptr [str1+2 (34301Ah)],eax // put 4 bytes to destination, earlier than the above example 0034101D mov cx,word ptr [str1+4 (34301Ch)] // HA, new register! Holding a word, which is exactly the left 2 bytes (after 4 bytes loaded to %eax) printf("New string: %s\n", str1); 00341024 push offset str1 (343018h) 00341029 push offset string "New string: %s\n" (342104h) 0034102E mov word ptr [str1+6 (34301Eh)],cx // Again, pulling the stored word back from the new register 00341035 call esi 

This is why I always choose memmove when trying to copy 2 overlapped memory blocks.

The difference between memcpy and memmove is that

  1. in memmove, the source memory of specified size is copied into buffer and then moved to destination. So if the memory is overlapping, there are no side effects.

  2. in case of memcpy(), there is no extra buffer taken for source memory. The copying is done directly on the memory so that when there is memory overlap, we get unexpected results.

These can be observed by the following code:

//include string.h, stdio.h, stdlib.h int main(){ char a[]="hare rama hare rama"; char b[]="hare rama hare rama"; memmove(a+5,a,20); puts(a); memcpy(b+5,b,20); puts(b); } 

Output is:

hare hare rama hare rama hare hare hare hare hare hare rama hare rama 
4

C11 standard draft

The C11 N1570 standard draft says:

7.24.2.1 "The memcpy function":

2 The memcpy function copies n characters from the object pointed to by s2 into the object pointed to by s1. If copying takes place between objects that overlap, the behavior is undefined.

7.24.2.2 "The memmove function":

2 The memmove function copies n characters from the object pointed to by s2 into the object pointed to by s1. Copying takes place as if the n characters from the object pointed to by s2 are first copied into a temporary array of n characters that does not overlap the objects pointed to by s1 and s2, and then the n characters from the temporary array are copied into the object pointed to by s1

Therefore, any overlap on memcpy leads to undefined behavior, and anything can happen: bad, nothing or even good. Good is rare though :-)

memmove however clearly says that everything happens as if an intermediate buffer is used, so clearly overlaps are OK.

C++ std::copy is more forgiving however, and allows overlaps: Does std::copy handle overlapping ranges?

3

As already pointed out in other answers, memmove is more sophisticated than memcpy such that it accounts for memory overlaps. The result of memmove is defined as if the src was copied into a buffer and then buffer copied into dst. This does NOT mean that the actual implementation uses any buffer, but probably does some pointer arithmetic.

compiler could optimize memcpy, for example:

int x; memcpy(&x, some_pointer, sizeof(int)); 

This memcpy may be optimized as: x = *(int*)some_pointer;

3

The code given in the links for memcpy seems to confuse me a bit, as it does not give the same output when I implemented it using the below example.

#include <memory.h> #include <string.h> #include <stdio.h> char str1[11] = "abcdefghij"; void *memcpyCustom(void *dest, const void *src, size_t n) { char *dp = (char *)dest; const char *sp = (char *)src; while (n--) *dp++ = *sp++; return dest; } void *memmoveCustom(void *dest, const void *src, size_t n) { unsigned char *pd = (unsigned char *)dest; const unsigned char *ps = (unsigned char *)src; if ( ps < pd ) for (pd += n, ps += n; n--;) *--pd = *--ps; else while(n--) *pd++ = *ps++; return dest; } int main( void ) { printf( "The string: %s\n", str1 ); memcpy( str1 + 1, str1, 9 ); printf( "Actual memcpy output: %s\n", str1 ); strcpy_s( str1, sizeof(str1), "abcdefghij" ); // reset string memcpyCustom( str1 + 1, str1, 9 ); printf( "Implemented memcpy output: %s\n", str1 ); strcpy_s( str1, sizeof(str1), "abcdefghij" ); // reset string memmoveCustom( str1 + 1, str1, 9 ); printf( "Implemented memmove output: %s\n", str1 ); getchar(); } 

Output :

The string: abcdefghij Actual memcpy output: aabcdefghi Implemented memcpy output: aaaaaaaaaa Implemented memmove output: aabcdefghi 

But you can now understand why memmove will take care of overlapping issue.

I have tried to run same program using eclipse and it shows clear difference between memcpy and memmove. memcpy() doesn't care about overlapping of memory location which results in corruption of data, while memmove() will copy data to temporary variable first and then copy into actual memory location.

While trying to copy data from location str1 to str1+2, output of memcpy is "aaaaaa". The question would be how? memcpy() will copy one byte at a time from left to right. As shown in your program "aabbcc" then all copying will take place as below,

  1. aabbcc -> aaabcc

  2. aaabcc -> aaaacc

  3. aaaacc -> aaaaac

  4. aaaaac -> aaaaaa

memmove() will copy data to temporary variable first and then copy to actual memory location.

  1. aabbcc(actual) -> aabbcc(temp)

  2. aabbcc(temp) -> aaabcc(act)

  3. aabbcc(temp) -> aaaacc(act)

  4. aabbcc(temp) -> aaaabc(act)

  5. aabbcc(temp) -> aaaabb(act)

Output is

memcpy : aaaaaa

memmove : aaaabb

4