为什么这会导致缓冲区溢出?

时间:2013-08-13 14:29:46

标签: c++

我正在阅读“编程大师”,在Stroustup的介绍性章节中,他提到:

char buf[MAX_BUF];
gets(buf);

会导致缓冲区溢出,但是:

string s;
cin >> s;

不会。有人可以向我解释一下吗?

5 个答案:

答案 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更改为更大数字的问题。