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的处理措施:
   当源内存的首地址等于目标内存的首地址时,不进行任何拷贝
   当源内存的首地址大于目标内存的首地址时,实行正向拷贝
   当源内存的首地址小于目标内存的首地址时,实行反向拷贝

 

posted @ 2017-01-07 17:52  牧 天  阅读(788)  评论(0)    收藏  举报