我很困惑,如果这很明显我很抱歉,但是:
int main()
{
char stringDest[20];
char stringSource[20];
strcpy_s(stringDest, stringSource);
return 0;
}
引发异常“缓冲区太小”。鉴于:
char stringSource[20];
int main()
{
char stringDest[20];
strcpy_s(stringDest, stringSource);
return 0;
}
工作正常。
此外,我认为安全strcpy_s(dest, size, source)
的重点在于您指定了复制的字节数,但是当我这样做时:
int main()
{
char stringDest[20];
char stringSource[20];
strcpy_s(stringDest, 1, stringSource);
return 0;
}
我得到“缓冲区太小异常”。
我感到很困惑。为什么在main()
之外声明变量会产生影响?为什么指定要复制的1个字节是错误的?
答案 0 :(得分:5)
给我一个未处理的RangeChecks异常,而:
C&C的数组是零索引的,这意味着对于char stringSource[20];
,元素从0到19,当你执行stringSource[20] = '\0';
时,访问超出数组边界,这导致未定义行为。
引发异常"缓冲区太小"。鉴于:
因为stringSource
是自动存储而且未初始化为有效字符串,所以使用它会导致未定义的行为。
在第二种情况下,当你将char stringSource[20];
放出函数时,数组是静态存储,默认情况下初始化为零值,它实际上与char stringSource[20] = "";
相同,即&# 39;这就是strcpy
成功的原因。
答案 1 :(得分:2)
您在这里调用未定义的行为,因为您没有初始化源字符串。
在大多数情况下,会有垃圾,第一个0
字节很可能在20的长度之后,这就是编译器/运行时抱怨的原因。
char stringSource[20] = {0};
或者
char stringSource[20] = "";
无论什么最适合。
根据您的环境,在调试版本中,编译器可以有意使用0xff
等值填充变量,以便第一个0-byte
始终超出限制。
如果你将char stringDest[20]
放在函数之外,那么它将是一个全局变量,CRT启动时它总是被0
所取代。
在上一个示例中,您应该查看strcpy_s的说明。
如果
,此变体将导致错误destsz小于或等于strnlen_s(src,destsz);换句话说,会发生截断
strcpy_s(stringDest, 1, stringSource);
表示1
小于未初始化的stringlen,因此会出错。
请注意,此参数不会告诉函数应该复制多少个字符,但是目标应该有多大。你不能告诉它只复制一个字符,你告诉它,它最多可以复制1个字符(无论如何都需要0字节)。