问题历史
安全的内存复制是C语言中最常见且最关键的任务之一。最初,程序使用循环进行逐字节复制。后来的标准函数包括:memcpy、memmove,以及像strncpy这样的更安全的字符串替代品。不正确的复制会导致缓冲区溢出和安全漏洞。
问题
使用不合适的函数或错误的大小进行复制可能会破坏数据,甚至可能被安全感兴趣的第三方利用。区分在何种情况下使用memmove,何时可以使用memcpy,对于避免内存重叠错误是至关重要的。
解决方案
对于安全地复制非字符串内存,请使用:
memcpy(dest, src, n);
memcpy快速地将n字节从src复制到dest,如果它们的内存区域不重叠。memmove:memmove(dest, src, n);
对于字符串的复制,最好使用strncpy,或者更好的是,如果可用,现代且安全的替代品strlcpy。
关键特点:
memcpy仅在src和dest不重叠时安全。memmove即使在内存区域重叠时也能正确工作。1. memcpy和memmove有何区别,何时需要使用哪种函数?
memcpy非常快速,但不适用于重叠的内存区域——结果会变得不可预测。memmove保证无论重叠情况如何,都会正确复制:
int arr[] = {1,2,3,4,5}; // memmove:安全地复制重叠 memmove(arr+1, arr, 4 * sizeof(int));
2. 使用strcpy将字符串复制到较小的缓冲区是否安全?
不,strcpy函数不会检查目标缓冲区的大小。这通常会导致缓冲区溢出。最好使用strncpy,或者strlcpy(如果可用),或者显式地控制大小:
char dest[5]; strncpy(dest, src, sizeof(dest)-1); // src应少于5个字符
3. 可以使用memcpy复制包含指针的结构体吗?
可以,但这只会复制指针本身,而不是那些地址上的数据。这可能导致内存操作错误和双重释放。
使用strcpy将长字符串复制到小缓冲区而不检查源长度。导致缓冲区溢出,造成安全漏洞。
优点:
缺点:
使用strncpy或memmove,并精确控制大小,手动确保字符串以零字符结束。
优点:
缺点: