I am trying to implement the memmove()
function for a certain quiz, so I dynamically allocated a block of memory with the ptr buffer as temp holder in the swap operation and the swap is done in one loop. When I submit this code it gives me one wrong answer out of 3 test cases. When I separate the swap in two for loops, all cases succeed. So what is the difference ?
swap in the same loop (One Case Wrong):
uint8_t *my_memmove(uint8_t *src, uint8_t *dst, size_t length) { uint8_t *buffer; buffer = (uint8_t*)reserve_words(length); for (uint8_t i = 0; i < length; i++) { *(buffer+i) = *(src+i); *(dst+i) = *(buffer+i); } return dst; free_words((uint32_t*)buffer); }
swap in two loops (All Cases Succeed):
uint8_t *my_memmove(uint8_t *src, uint8_t *dst, size_t length) { uint8_t *buffer; buffer = (uint8_t*)reserve_words(length); for (uint8_t i = 0; i < length; i++) { *(buffer+i) = *(src+i); } for (uint8_t i = 0; i < length; i++) { *(dst+i) = *(buffer+i); } return dst; free_words((uint32_t*)buffer); }
reserve_words function used (user_defined) :
int32_t *reserve_words(size_t length) { int32_t *ptr; ptr = (int32_t *)malloc(length * sizeof(int32_t)); return ptr; }
The problem here is that memmove is guaranteed to work with overlapping memory blocks. If you want to see a case where your first version would fail, try this:
The output is:
It's easy to realize why. Every iteration you will write to the byte you're going to read from next iteration.
So your first version of
my_memmove
should really be calledmy_memcpy
instead, becausememcpy
is not guaranteed to work with overlapping memory areas, whichmemmove
is.