Company coding standards prohibit the use of unsafe functions and require the use of custom safe functions developed internally. In C language, some functions are not absolutely safe, such as memcpy which may have overlapping memory regions; strcpy, gets, and sprintf do not check the size of the target buffer; and scanf series (which do not limit the read length), etc. Both memcpy and memmove are memory copy functions that copy n bytes from the src memory area to the dest memory area, but there is a possibility of memory overflow during the copy, although the probability is very low, and the compiler itself also has certain optimizations.memcpy prototype: void *memcpy (void *_Dst, const void *_Src, size_t _Size);memmove prototype: void *memmove(void *_Dst,const void *_Src,size_t _MaxCount);The difference is that in memcpy, the src and dest memory areas must not overlap, otherwise an exception will occur. In contrast, the memory areas in memmove may overlap; the copying process of memmove is as if the content from src is first copied to a non-overlapping temporary array, and then the content is copied from the temporary array to dest, making it relatively safer.If an exception occurs due to memory overlap, it is a serious issue, as memory corruption problems are generally difficult to trace and take a long time to locate.The implementation principles of memcpy and memmove functions are roughly as follows; here is a simple reference:
void *Memcpy(void *dest, const void *src, size_t count)
{
if (NULL == dest || NULL == src || 0 >= count) return NULL;
char *d = (char *) dest;
char *s = (char *) src;
while (count--)
{
*d++ = *s++;
}
return dest;
}
void *Memmove(void *dest, const void *src, size_t count)
{
if (NULL == dest || NULL == src || 0 >= count) return NULL;
if (dest < src) // Copy from front to back
{
char *d = (char *) dest;
char *s = (char *) src;
while (count--)
{
*d++ = *s++;
}
}
else // Copy from back to front
{
char *d = (char *) dest + count;
char *s = (char *) src + count;
while (count--)
{
*--d = *--s;
}
}
return dest;
}
The code may not be very rigorous, but the implementation principle is as described above, for ease of understanding. Overall, memmove is slightly more complex than memcpy, as it needs to distinguish whether the destination address is in front or behind. If the destination address is in front, it copies the string from the src address from front to back; otherwise, it copies the string from the src address from back to front. In simple terms, memcpy copies from front to back, while memmove can copy from back to front.For example, you can verify the following code with different compilers:
#include "stdio.h"
#include "string.h"
int main()
{
char str1[] = "hello world";
char str2[] = "hello world";
memcpy(str1 + 2, str1, 5);
printf("%s\n", str1);
memcpy(str2 + 2, str2, 5);
printf("%s\n", str2);
return 0;
}
The output of the above program may vary depending on the compiler used.Regardless, memcpy does not guarantee handling overlapping regions; even if it appears to work correctly in some cases, it is still considered undefined behavior, making the code unreliable and posing risks for portability. Therefore, unless it can be ensured that the memory regions will not overlap, memmove should be preferred. Modern compilers are quite good at optimization, and the performance of both is actually quite close, but the safety of memmove far exceeds that of memcpy.To be precise, memmove is not considered an “unsafe function” because the function has no inherent flaws; it simply does not automatically check the size of the target buffer. If the programmer incorrectly specifies the copy length, it can lead to buffer overflow. It relies on the programmer to correctly control the length of the copy, and the same applies to other memory copy functions. Therefore, if the copy length comes from user input or other external data, legality checks must be performed. For example:
int length = GetInputLength();
if (sizeof(dest) < length)
{
// Error handling
}
else
{
memmove(dest, src, length);
}
Debugging environment: Windows Eclipse + Visual Studio 2022