Hi ,

when i run the program i got the same out put by using memcpy and memmove
but i dont understand the difference between them.

manual page says that memory area should not overlap in memcpy but can in memmove.

what is meant by moving memory and how its safe . why memcpy is dangerous.

int main() {

        char strmc[]="strings are good";
        char strmm[]="strings are good";

        printf("before memcyp : the string <%s> \n", strmc);
        memcpy(strmc+1,strmc+0,4);
        printf("after memcpy the string <%s> \n",strmc);

        printf("before memmove : the string <%s> \n", strmm);
        memmove(strmm+1,strmm+0,4);
        printf("after memmove the string <%s> \n",strmm);

return 0;
}

the out put what i got is :

before memcyp : the string <strings are good>
after memcpy the string <sstrigs are good>
before memmove : the string <strings are good>
after memmove the string <sstrigs are good>

Recommended Answers

All 3 Replies

>when i run the program i got the same out put by using memcpy and memmove
There's nothing stopping an implementation from implementing memcpy in terms of memmove. Further, calling memcpy on overlapping memory invokes undefined behavior. It may or may not fail.

>what is meant by moving memory and how its safe. why memcpy is dangerous.
memcpy does a mindless copy, regardless of whether there are shared bytes between the source and destination:

void *memcpy (void *dst, const void *src, size_t n)
{
  char *a = dst;
  const char *b = src;

  while (n--)
    *a++ = *b++;

  return dst;
}

If dst and src share bytes within n, anything could technically happen, but let's assume a very simple common scenario. Say you want to do memmove(array + 1, array, 2) where array is defined as a string ("abc"). With memmove you'd expect the result to be "aab", but with memcpy that might not happen. Here's what could happen with the above algorithm:

a = "bc", b = "abc, *a++ = *b++ == "aac"
a = "c",  b = "ac", *a++ = *b++ == "aaa"
done

So the result is "aaa"...hmm, not quite right, is it? memmove fixes this problem by checking for overlap and adjusting the logic to do something safer, and at a glance it's easy to see that the function can be slightly slower:

void *memmove(void *dst, const void *src, size_t n)
{
  char *a = dst;
  const char *b = src;

  if (a <= b || b >= (a + n)) {
    /* No overlap, use memcpy logic (copy forward) */
    while (n--)
      *a++ = *b++;
  }
  else {
    /* Overlap detected! Copy backward to fix */
    a = a + n - 1;
    b = b + n - 1;

    while (n--)
      *a-- = *b--;
  }

  return dst;
}

These algorithms are naive, but memcpy is less restricted and thus more open to optimization. However, in my experience, memmove isn't likely to be a bottleneck, so removing the risk of undefined behavior by using memmove instead of memcpy is worth it.

commented: Nice +19
commented: Very good explanation. +26

If dst and src share bytes within n, anything could technically happen, but let's assume a very simple common scenario. Say you want to do memmove(array + 1, array, 2) where array is defined as a string ("abc"). With memmove you'd expect the result to be "aab", but with memcpy that might not happen. Here's what could happen with the above algorithm:

a = "bc", b = "abc, *a++ = *b++ == "aac"
a = "c",  b = "ac", *a++ = *b++ == "aaa"
done

So the result is "aaa"...hmm, not quite right, is it? memmove fixes this problem by checking for overlap and adjusting the logic to do something safer, and at a glance it's easy to see that the function can be slightly slower:

These algorithms are naive, but memcpy is less restricted and thus more open to optimization. However, in my experience, memmove isn't likely to be a bottleneck, so removing the risk of undefined behavior by using memmove instead of memcpy is worth it.

Please have a look at this program.

if i use your definitions the out is same as you explained , but when i use standard functions the out put of memmove and memcpy are same.

if memmove and memcpy are implemented differently then we should get different out put using those functions.

but it is not the case with std functions.

you said overlap might cause problem in memcpy.

does the standard definition of memcpy varies from system to system ?

please verify out pit by commenting and uncommenting the definitions of memcpy and memmove.

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

int main()
{

        char mc[]="abc";
        char mm[]="abc";

        memcpy(mc+1, mc , 2 );
        memmove( mm+1 , mm , 2);

        printf("%s \n", mc );
        printf("%s \n", mm );
        return 0;
}

#if 0

void *memcpy (void *dst, const void *src, size_t n)
{
  char *a = dst;
  const char *b = src;

  while (n--)
    *a++ = *b++;

  return dst;
}

void *memmove(void *dst, const void *src, size_t n)
{
  char *a = dst;
  const char *b = src;

  if (a <= b || b >= (a + n)) {
    /* No overlap, use memcpy logic (copy forward) */
    while (n--)
    *a++ = *b++;
  }
  else {
    /* Overlap detected! Copy backward to fix */
    a = a + n - 1;
    b = b + n - 1;

    while (n--)
      *a-- = *b--;
  }

  return dst;
}

#endif

> does the standard definition of memcpy varies from system to system ?
No, the standard DEFINITION is that it copies n bytes from source to destination.

The IMPLEMENTATION from one system to another can however vary.
- some systems copy from low addresses to high addresses - starting at src[0] to src[n-1]
- other systems copy from high to low - src[n-1] to src[0]

If the blocks do not overlap, then there isn't a problem.
If the blocks DO overlap, then you risk trashing the data before you've copied it (and no way to guess which way your system does it).

Memmove() exists to always do the right thing.

commented: If you ask me, Salem exists to always do the right thing. :P +13
Be a part of the DaniWeb community

We're a friendly, industry-focused community of developers, IT pros, digital marketers, and technology enthusiasts meeting, networking, learning, and sharing knowledge.