字符串副本是说缓冲区太小,strcpy_s源问题

时间:2016-05-12 12:43:38

标签: c++ c string char strcpy

我很困惑,如果这很明显我很抱歉,但是:

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个字节是错误的?

2 个答案:

答案 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字节)。