众所周知,strcpy_s是strcpy的安全版本。
但我想知道它是如何运作的......
让我们看一些例子。
strpy_s的声明:
errno_t strcpy_s(_CHAR * _DEST,size_t _SIZE,const _CHAR * _SRC)
EG1
char dest[5];
char* src = "abcdefg";
strcpy_s(dest,5,src);
它会返回一个断言 我想我能理解这一点,使用 _SIZE 来确保我们无法复制比 _SIZE
更多的字符但是......我无法理解这一点:
char dest[5];
char* src = "abcdefg";
strcpy_s(dest,10,src);
我们仍然可以得到一个断言,这是怎么发生的?
ps,错误是:
调试断言失败
表达式:(L"缓冲区太小"&& 0)
在VS2013中
strcpy_s会检查其体内dest的大小吗?如果它是真的,怎么样?如何检查像_DEST这样的指针?
答案 0 :(得分:8)
这实际上是如何在运行时获取堆栈数组的大小而不将其衰减为指针:
template<typename T, size_t N>
size_t arrSize(T (&array)[N])
{
return N;
}
您将其作为模板参考发送,模板机制会推断出尺寸。所以,你可以做类似
的事情int myArray[10];
cout << arrSize(myArray); // will display 10
所以我猜这就是&#34;安全&#34; MS strcpy_s
正在检查尺寸。否则,如果你只传递一个指针,就没有标准的顺应方式来获取大小。
答案 1 :(得分:2)
在DEBUG模式下,MicroSoft API使用0xfd填充缓冲区,因此可以检查溢出。
此函数不会截断复制的字符串,但会引发异常!
指定dest缓冲区的大小总是很痛苦(使用_countof而不是sizeof),主要是在使用指针时!
我对那些“_s”API比使用标准API有更多问题!!
答案 2 :(得分:1)
dest
不能超过5个字符,这就是您收到错误的原因。这不是因为_SIZE
。如果dest
为char*
,那么您需要确保为其分配足够的内存,否则不会出现任何编译错误。但是在你的程序dest
中有一个固定的大小,strcpy_s
与strcpy
不同,检查目标缓冲区的大小(如果可以的话,在这种情况下,它的大小可以是在编译时定义)。
阅读本文
http://www.cplusplus.com/forum/beginner/118771/
基本上strcpy_s
是strcpy
的“安全”版本,它不允许您溢出。
从标准:
C(2011)和ISO / IEC WDTR 24731 - strcpy_s
:strcpy
的变体,用于在复制之前检查目标缓冲区大小。在内部,可能strcpy_s
断言sizeof(dest)<SIZE
。
答案 3 :(得分:1)
MSDN说“strcpy_s函数将strSource地址中的内容(包括终止空字符)复制到strDestination指定的位置。 目标字符串必须大到足以保留源字符串及其终止空字符 。如果源字符串和目标字符串重叠,则strcpy_s的行为是未定义的。“