数组堆栈溢出

时间:2012-04-14 15:42:41

标签: c

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

enter image description here

第一行

555555555555555555555555555555555

被放入。

为什么str55555555555?为什么str不是8888888888888888855555555555588888

4 个答案:

答案 0 :(得分:6)

重写t缓冲区,并到达str缓冲区,其中输入的其余部分和空终止符已设置。并且puts仅打印到空终止符。

看起来很像:

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

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

顺便说一下,这是一个缓冲区溢出,而不是堆栈溢出,但是在这个代码上可以进行堆栈溢出。

答案 1 :(得分:1)

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

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

如果你看到gets documentation

  

请注意,get的行为与fgets对stdin的行为完全不同   参数:首先,结尾的换行符不包括在内   与fgets一起得到它。第二,得到不让你指定   要读取多少个字符的限制,所以你必须小心   str指向的数组大小,以避免缓冲区溢出。

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

答案 2 :(得分:1)

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

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

最后,它显示t的内容,但由于该字符串不以空字符结尾,因此它会继续显示内存(这是指向str的缓冲区),直到遇到所有5之后的空字符。

答案 3 :(得分: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;
    }