Please look into this inexplicable behavior and output of memcpy() for overlapping memory blocks

StackOverflow https://stackoverflow.com/questions/16535795

  •  29-05-2022
  •  | 
  •  

Question

After reading the following about memcpy(), I proceeded to read about memmove():

To avoid overflows, the size of the arrays pointed by both the destination and source parameters, shall be at least num bytes, and should not overlap (for overlapping memory blocks, memmove is a safer approach).(LINK)

And after checking the program used to illustrate the working of memmove() I decided to tweak it by using memcpy() instead to see how different is the output.To my surprise,they are the same even if it's a case of overlapping memory blocks.Here is the program and the output,and I have proceeded to describe my confusion after that:

#include <stdio.h>
#include <string.h>

int main ()
{
  char str[] = "memmove can be very useful......";
  //memmove (str+20,str+15,11);
  memcpy(str+20,str+15,11);  //Simply used memcpy instead of memmove
  puts (str);
  return 0;
}

Output memmove can be very very useful.

This output is the same as it is for memmove().And here are my confusions:

1) Why is output same for both?Since there is no intermediate buffer used in case of memcpy(),I expect the copy to start by copying the character in str+15 position to the str+20 position (overwriting what is there),character in str+16 position to str+21 position, and so on till character in str+20 position,which has by now changed to the character in str+15 position, to be copied to the str+25 position.But it's not so,there is no overwriting and it's acting as if an intermediate buffer is used to write the exact original string.Here's an illustration:

memmove can be very useful......  //Original positions before memcopy
               ^    ^
            str+15  str+20

memmove can be very vseful......
                    ^ copies str+15 to str+20

memmove can be very veeful......
                     ^ copies str+16 to str+21
memmove can be very verful......
                      ^ copies str+17 to str+22
memmove can be very veryul......
                       ^copies str+18 to str+23
memmove can be very very l......
                        ^ copies str+19 to str+24
memmove can be very very v......
                         ^ I expect 'v' to be copied from str+20 to str+25
                           as str+20  now has 'v',not 'u'
memmove can be very very ve.....
                          ^ I expect 'e' to be copied from str+21 to str+26 
                            as str+21 now has 'e' not 's'

Then why is memcpy() copying it as memmove can be very very useful, instead of memmove can be very very very v ?

2) Now a minor secondary question arising from it.The following is said about memmove() (LINK)

Copying takes place as if an intermediate buffer were used, allowing the destination and source to overlap.

What exactly is as if here?Isn't an intermediate buffer really used for memmove()?

Was it helpful?

Solution

If the objects overlap, the behaviour of memcpy is undefined. There's little point in trying to reason about undefined behaviour. Since it is undefined it defies reason. You know the rules, and they are clearly documented. If the objects overlap, use memmove.

As for the use of "as if", that is to specify behaviour but not place any limitations on implementation. This allows the library implementor to use whatever method they see fit, so long as the end result is the same as using an intermediate buffer. For example, the implementation could detect that the objects do not overlap and so avoid using an intermediate buffer for performance reasons.

Licensed under: CC-BY-SA with attribution
Not affiliated with StackOverflow
scroll top