-1
    #include
    int main(void)
    {
        char str[100]="88888888888888";
        char t[20]="";
        gets(t);
        puts(str);
        puts(t);
        return 0;
    }

在此处输入图像描述

第一行

555555555555555555555555555555555

被放入。

为什么str55555555555?为什么str不是88888888888888888or 55555555555588888

4

4 回答 4

6

您覆盖了t缓冲区,并到达了str缓冲区,其中输入的其余部分和空终止符已设置。并且puts只打印到空终止符。

差不多是这样的:

[ t (20)             ][str(100)                                 ]
 55555555555555555555  5555555555555\0

请注意,虽然t被声明为char[20],但当您打印它时,您会得到完整的输入(长于 20),因为puts在空终止符处停止(再次)。

顺便说一句,这是缓冲区溢出,而不是堆栈溢出,但此代码也可能发生堆栈溢出。

于 2012-04-14T15:45:27.133 回答
1

正如 Binyamin 所说,这是由于输入字符串太长而触发的溢出引起的。然而,这有点随机——有时两个内存分配会紧挨着发生,字符串会扩展到相邻的变量,有时可能不会发生。

我建议你为这种溢出设置保护条件。

如果您在gets 文档中看到:

请注意,gets 的行为与 fgets 将 stdin 作为参数的行为不同:首先,结束换行符不包含在 get 中,而 fgets 包含。其次,gets 不允许您指定要读取的字符数的限制,因此您必须注意 str 指向的数组的大小以避免缓冲区溢出。

在您的情况下,如果您不知道大小 apriory 可能最好使用fgets它,因为它更安全(虽然有点慢)。

于 2012-04-14T15:47:50.883 回答
1

当您输入一个超过 20 5s 的字符串时,它会超出分配给t的缓冲区并扩展到分配给的缓冲区str

然后它显示 的内容str,即您输入的字符串,从第 21 个字符开始。

最后,它显示 的内容t,但由于该字符串不以空字符结尾,它会继续显示内存(分配给 的缓冲区str),直到在所有5s 之后遇到空字符。

于 2012-04-14T15:48:08.337 回答
0

为了避免这些分配重叠问题,您可以尝试这种替代方法,这样如果我没记错的话,分配会在运行时进行:

    #include <iostream>

    int main(void)
    {
      char *str;
      char *t;
      str = new char(100);
      str = (char*)"88888888888888";
      t = new char(20);
      std::cin >> t;
      puts(str);
      puts(t);
      return 0;
    }
于 2012-04-14T16:22:38.273 回答