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