6

So I am learning C and I have to implement the memset() and memcpy() functions.

I've looked them up in linux man pages and I saw that the first takes care of overlapping memory situations but the second doesn't,but I don't understand how memory overlapping occurs in C.

Can somebody please provide me some examples on strings?

Thank you very much.

1
  • are you sure it's memset not memmove?
    – kzidane
    Nov 1, 2015 at 10:30

5 Answers 5

22

I believe you mean memmove which takes care of memory overlapping as oppose to memset. but what is memory overlapping anyway?

suppose we have an array of 5 chars, where each char is a byte long

+++++++++++++++++++++++++++++++
| 'a' | 'b' | 'c' | 'd' | 'e' |
+++++++++++++++++++++++++++++++
 0x100 0x101 0x102 0x103 0x104

now according to the man page of memcpy, it takes 3 arguments, a pointer to the destination block of memory, a pointer to the source block of memory, and the size of bytes to be copied.

what if the destination is 0x102, the source is 0x100 and the size is 3? memory overlapping happens here. that is, 0x100 would be copied into 0x102, 0x101 would be copied into 0x103 and 0x102 would be copied into 0x104.

notice that we first copied into 0x102 then we copied from 0x102 which means that the value which was originally in 0x102 was lost as we overwrote it with the value we copied into 0x102 before we copy from it. so we would end up with something like

+++++++++++++++++++++++++++++++
| 'a' | 'b' | 'a' | 'b' | 'a' |
+++++++++++++++++++++++++++++++
 0x100 0x101 0x102 0x103 0x104

instead of

+++++++++++++++++++++++++++++++
| 'a' | 'b' | 'a' | 'b' | 'c' |
+++++++++++++++++++++++++++++++
 0x100 0x101 0x102 0x103 0x104

how does a function like memmove take care of memory overlapping? according to its man page, it first copies the bytes to be copied into a temporary array then pastes them into the destination block as oppose to a function like memcpy which copies directly from the source block to the destination block.

1
  • Good answer, but what if i allocated memory for destination using malloc and pass that pointer to memcpy? In this case malloc will give different address space which never overlap. So my question is what real time scenario and when it actually happened? Apr 21, 2020 at 11:51
1

Lets see:

memset: sets a memory segment to a constant value, so, there is no "overlapping" possible here, because there is just a unique, contiguous, memory segment to "set".

memcpy: you are reading from one memory segment and, well, copying it to another memory segment. If the memory segments coincide at some point, a "overlapping" would occur. Imagine a memory segment starts at address 0x51, and the other starts at address 0x70, and you try to copy 50 bytes from 0x51 to 0x70... at some point, the process will start reading from address at 0x70, and copying to address 0x8F. This is most likely not what you wanted to do.

At a lower level, in assembly, you should be able to find several ways of doing this, including MMX, SSE2 and other SIMD instructions. If you download glibc source code (https://www.gnu.org/software/libc/download.html), you will see some implementations done in assembly.

C is a "high-level" language, but is quite close to assembly, you can get memory address for variables and even for functions, so, it is quite powerful, allowing you to do all kind of things, like reading/writing an array after its "official" end (the OS will stop you once you try to access memory outside your process' memory), so, yes, memory overlapping is totally possible in C. Something like this would create two potentially overlapping memory "segments" (actually, the same segment, that I am manually dividing and assigning to two pointers).

This is a funny-behaving program, it is definitely, and intentionally buggy, just to show what kind of odd things can happen if memory do overlap with memcpy:

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

int main(void)
{
        char *a,*b;
        a=malloc(100*sizeof(char));
        b=(a+25);
        strcpy(a,"This is just a test");
        strcpy(b,"And this is another test, longer test string.");
        printf("a: %s\nb: %s\n",a,b);
        printf("Now, I am copying b in a, and lets see what happen...\n");
        memcpy(a,b,75);
        printf("a: %s\nb: %s\n",a,b);
}

Save it to a .c file, like test.c, and compile it using gcc, like this:

gcc -O0 -o test test.c

Run it and then try again compiling like that:

gcc -O2 -o test test.c

It will (most likely) behave differently.

Try replacing memcpy with strncpy and see what happen.

I hope the example is useful.

1

With memcpy, the destination cannot overlap the source at all. With memmove it can. This means that memmove might be very slightly slower than memcpy, as it cannot make the same assumptions.

For example, memcpy might always copy addresses from low to high. If the destination overlaps after the source, this means some addresses will be overwritten before copied. memmove would detect this and copy in the other direction - from high to low - in this case. However, checking this and switching to another (possibly less efficient) algorithm takes time.

0

*) The main difference between memcpy and memmove is,memcpy works on the same string but memmove works in separate memory by taking a copy of the string.
*) Due to this,overlapping happens in memcpy not in memmove
Let me explain you with an example.
I took a character array :

char s[20]="alightechs";

if i do the following operations separately,

memmove(s+5,s,7);  
memcpy(s+5,s,7); 



o/p for memmove is alighalighte  
o/p for memmove is alighalighal  

because moving or copying both happens single byte by byte.
till alighaligh, there is no problem in both the cases because dest=alighte(7 is the number of chars to copy/move),
while memcpy i'm copying from 5th position,

alightechs   
alighaechs  
alighalchs  
alighalihs  
alighaligs  
alighaligh  

till here there is no problem,it copied aligh(5 letters)
as,memcpy works on the same string,6th letter will be a and 7th letter will be l
i.,e every time the string is getting updated which results in undefined o/p as below
at 6th letter copying,
the updated string is s[20]=alighaligh
so we get now

alighaligha  
alighalighal    

the updation of actual string is nothing but overlap,
In the string "alightechs", techs is overlapped by aligh and the null left in the string are overlapped by te and other are null as same they are.

0

Am I doing things wrong? Aren't supposed "memcpy()" and "memmove()" to produce different results when overlap occurs? Check the following sample:

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

void symbcpy(char *dest, const char *src, size_t buffer);

int main () 
{
    char arr1[] = "Some string", arr2[] = "Some string", arr3[] = "Some string", arr4[] = "Some string";

    printf("\nBefore:\narr1: %s\narr2: %s\narr3: %s\n", arr1, arr2, arr3);

    strncpy(&arr1[2], &arr1[0], 5);
    memcpy(&arr2[2], &arr2[0], 5);
    memmove(&arr3[2], &arr3[0], 5);
    symbcpy(&arr4[2], &arr4[0], 5);

    printf("\nAfter:\narr1: %s\narr2: %s\narr3: %s\narr4: %s\n", arr1, arr2, arr3, arr4);

    return(0);
}

/*
symbcpy is how I expected memcpy to work.
I know that memcpy returns value of type "void *", but that's not the matter here.
*/
void symbcpy(char *dest, const char *src, size_t buffer)
{
    for (int i = 0; i < buffer; i++)
    {
        dest[i] = src[i];
    }
    
}

I tested this code on several online compilers. They produced the following result:

https://www.onlinegdb.com/online_c_compiler Output:

Before:
arr1: Some string
arr2: Some string
arr3: Some string
arr4: Some string

After:
arr1: SoSome ring
arr2: SoSome ring
arr3: SoSome ring
arr4: SoSoSoSring

https://ide.geeksforgeeks.org/ Output:

Before:
arr1: Some string
arr2: Some string
arr3: Some string
arr4: Some string

After:
arr1: SoSome ring
arr2: SoSomemring
arr3: SoSome ring
arr4: SoSoSoSring

https://www.programiz.com/c-programming/online-compiler/ Output:

Before:
arr1: Some string
arr2: Some string
arr3: Some string
arr4: Some string
After:
arr1: SoSome ring
arr2: SoSome ring
arr3: SoSome ring
arr4: SoSoSoSring

You must log in to answer this question.

Not the answer you're looking for? Browse other questions tagged .