strcpy()是依据源串的/0作为结束判断的,不检查copy先的Buffer的Size,如果目标空间不够,就有BufferOverflow问题。请务必使用按照strncpy_s()、strcpy_s()、strncpy()等不同环境而准备的安全度很高的函数。
strcpy函数,就象gets函数一样,它没有方法来保证有效的缓冲区尺寸,所以它只能假定缓冲足够大来容纳要拷贝的字符串。在程序运行时,这将导致不可预料的行为。
另外、即使是使用安全度很高的函数,由于用法方面的原因,也可能发生Buffer Overflow,请注意如下几点。不要在strcpy_s()、strncpy_s()进行Buffer Size的誤指定。
strcpy_s()两个参数和三个参数的不同用法区别如下代码所示:
第二个参数表示目标缓冲区大小,大于或等于源串的长度+1(存放结束符/0),strcpy_s必须完全拷贝源串,若只想拷贝一部分源串则应该用strncpy_s函数。
若使用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函数的安全性增强版本