#include
int main(void)
{
char str[100]="88888888888888";
char t[20]="";
gets(t);
puts(str);
puts(t);
return 0;
}
第一行
555555555555555555555555555555555
被放入。
为什么str
是55555555555
?为什么str
不是88888888888888888
或55555555555588888
?
答案 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;
}