C溢出
strncpy、strncat等带n版本的字符串操作函数在源字符串长度超出n标识的长度时,会将包括’\0’结束符在内的超长字符串截断,导致’\0’结束符丢失。这时需要手动为目标字符串设置’\0’结束符。
strcpy() sprintf() strcat() 存在安全隐患, 其对应的安全版为:strncpy() snprintf() strncat()
char *strncpy(char *dest, const char *src, int n) 不自动添加'\0'
int snprintf(char *str, size_t size, const char *format, ...)会自动添加'\0'
void test(int argc, char *argv[]) { char dst[256]; if ( argc > 1 ) { strcpy(dst, argv[1]); // 源字符串长度可能大于目标数组空间,造成缓冲区溢出 } }
推荐的写法
void test(int argc, char *argv[]) { char *dst = NULL; if ( argc > 1 ) { dst = (char *)malloc(strlen(argv[1]) + 1); if( dst != NULL ) { strncpy(dst, argv[1], strlen(argv[1])); dst[strlen(argv[1])] = ’\0’; } } /*...dst使用后free...*/ }
char *tmp = NULL; memset(dst, '1', sizeof(dst)); memcpy(dst, src, strlen(src)); //这里必须保证strlen(src) < sizeof(dst),否则dst后面的数据可能被覆盖 dst[sizeof(dst) - 1] = ’\0’; //修改dst以’\0’结尾
char dst[5]; char src[] = "657321"; //strncpy(dst, src, 7); // 如果这么写会导致其他数据被覆盖 strncpy(dst, src, sizeof(dst)); // dst[sizeof(src) - 1] = '\0'; //不管src长度是多少,加上这行才始终不会越界 printf(dst); //越界
#include<stdio.h> #include<string.h> int main(void) { char dest[4]; char src[6] = "World"; //strncpy(dest, src, 10); // 则输出为“World” 显然会覆盖数据 strncpy(dest, src, sizeof(dest)); // 则输出为“Worl” printf("%s\n", dest); return 0; }
memcpy与memmove的目的都是将N个字节的源内存地址的内容拷贝到目标内存地址中。地址不重叠时,功能和原理相同。
但当源内存和目标内存存在重叠时,memcpy会出现错误,而memmove能正确地实施拷贝,但这也增加了一点点开销。
memmove的处理措施:
当源内存的首地址等于目标内存的首地址时,不进行任何拷贝
当源内存的首地址大于目标内存的首地址时,实行正向拷贝
当源内存的首地址小于目标内存的首地址时,实行反向拷贝

浙公网安备 33010602011771号