我正在阅读“编程大师”,在Stroustup的介绍性章节中,他提到:
char buf[MAX_BUF];
gets(buf);
会导致缓冲区溢出,但是:
string s;
cin >> s;
不会。有人可以向我解释一下吗?
答案 0 :(得分:7)
没有办法告诉gets
函数缓冲区中有多少空间。它只是将接收输入写入您发送给它的缓冲区。如果有更多的输入而不是有空间,那么它就会幸福地超出界限。
std::string
是一个跟踪大小的容器,它会动态增长以适应输入。
gets
无可救药地破坏了功能。永远不要使用它。
编辑:正如詹姆斯坎泽指出的那样,gets
已经从C语言库中删除了。
答案 1 :(得分:5)
gets
会一直读到'\n'
。如果有更多
一行中有MAX_BUF
个字符,它会继续写
它们超出缓冲区的末尾。 (gets
已被弃用
因为没有办法安全地使用它。)
cin >> s
读取,直到找到空格(所以语义
是不一样的),如果需要,会增长字符串。因为
它增长了“缓冲区”,它永远不会超越结束
它
答案 2 :(得分:3)
与通过引用传递给std::string
并且可以修改的operator >>
不同,buf
是固定的,它由指针传递。缓冲区只能容纳您分配的数据,并且不能随用户输入的大小增长。 gets
不知道缓冲区的限制在哪里,因此它不会检查它,可能写入已分配空间的末尾。这是未定义的行为,可以利用这些行为用代表heap spraying kind的恶意攻击的可执行代码的数据填充内存。
如果签名为gets(char **)
,则gets
的作者可能需要malloc
- ed空格并使用realloc
来扩展缓冲区;但是,考虑到当前指定API的方式,即使理论上也无法修复溢出。
这个问题非常严重,C库的设计者决定在即将推出的语言标准中从标准库中删除gets
。
答案 3 :(得分:2)
界面完全不同。在第一种情况下,内存缓冲区具有固定大小,并且大小不会传递给函数gets
,因此它无法控制它是否超出限制。
在第二种情况下,内存缓冲区由std::string
管理,该函数将确保它根据需要增长。也就是说,std::string
将增长,以便为整个输入提供足够的空间。
答案 4 :(得分:1)
gets()不会检查长度,所以你可以在没有任何边界检查的情况下超过MAX_BUF(因为c / c ++没有边界检查)。通常在编译时或运行时,您将收到有关gets()不安全的警告。您应该使用执行某些检查的函数。 std :: string将动态调整大小以适应您放入其中的任何大小数据,因此它可能只是将MAX_BUF更改为更大数字的问题。