strcpy/strncpy/strcpy_s比较

转载自:http://blog.csdn.net/caomiao2006/article/details/4766416

strcpy()是依据源串的/0作为结束判断的,不检查copy先的Buffer的Size,如果目标空间不够,就有BufferOverflow问题。请务必使用按照strncpy_s()、strcpy_s()、strncpy()等不同环境而准备的安全度很高的函数。

      strcpy函数,就象gets函数一样,它没有方法来保证有效的缓冲区尺寸,所以它只能假定缓冲足够大来容纳要拷贝的字符串。在程序运行时,这将导致不可预料的行为。
  另外、即使是使用安全度很高的函数,由于用法方面的原因,也可能发生Buffer Overflow,请注意如下几点。不要在strcpy_s()、strncpy_s()进行Buffer Size的誤指定。

      strcpy_s()两个参数和三个参数的不同用法区别如下代码所示:

 

[c-sharp] view plain copy
  1. char *str1=NULL;  
  2. str1=new char[20];  
  3. char str[7];  
  4. strcpy_s(str1,20,"hello world");//三个参数  
  5. strcpy_s(str,"hello");//两个参数但如果:char *str=new char[7];会出错:提示不支持两个参数  

       第二个参数表示目标缓冲区大小,大于或等于源串的长度+1(存放结束符/0),strcpy_s必须完全拷贝源串,若只想拷贝一部分源串则应该用strncpy_s函数。


[cpp] view plain copy
  1. char * dst = (char *)malloc(10);  
  2. //strcpy_s(dst, 10, "Hello world!");  
  3. strncpy(dst, "Hello world!", 10);  

      若使用strncpy不会出错,观察内存可以发现,目标指针所指的缓冲区中完全是从源字符串拷贝过来的字符,没有/0结束符,但是若使用strcpy_s则在运行是出现断言出错,所以strncpy仍然不是安全的,因为有可能出现目标指针的字节数不足存放源指针所指向的内容。另外,若使用语句strncpy(dst, "Hello", 10);则会把剩下的空间都填充为空字符/0,带来效率问题,strcpy_s则不会。

     所以从VS2005开始已经推出相应的安全版本——strcpy_s(末尾的s可能代表safe)。

     接口的定义改变如下:

char* strcpy(char* dest, const char* src) --> errno_t strcpy_s(char* dest, size_t numElems, const char* src)

char* strcpy(char* dest, const char* src, size_t count) --> errno_t strcpy_s(char* dest, size_t numElems, const char* src, size_t count)

     后者之所以比前者安全,是因为他们在接口增加了一个参数numElems来表明dest中的字节数,防止目标指针dest中的空间不够而导致出现Bug,同时返回值改成返回错误代码,而不是为了一些所谓的方便而返回char*。这样接口的定义就比原来安全很多。

 

     更多关于CRT安全性修改的函数参见另一篇文章(转):VS 2005 CRT函数的安全性增强版本

原文地址:https://www.cnblogs.com/pzqu/p/9457623.html