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

C++ 为什么这会导致缓冲区溢出?,c++,C++,我在读《编程大师》,在Stroustup的介绍章节中,他提到: char buf[MAX_BUF]; gets(buf); 将导致缓冲区溢出,但: string s; cin >> s; 不会。有人能给我解释一下吗?无法告诉gets函数缓冲区中有多少空间。它只是将接收到的输入写入发送到的缓冲区。如果输入比空间多,很可能会超出范围 另一方面,string是一个跟踪大小的容器,它将动态增长以适应输入 gets是一个彻底崩溃的函数。永远不要用它 编辑:正如James Kanze指出的,

我在读《编程大师》,在Stroustup的介绍章节中,他提到:

char buf[MAX_BUF];
gets(buf);
将导致缓冲区溢出,但:

string s;
cin >> s;
不会。有人能给我解释一下吗?

无法告诉gets函数缓冲区中有多少空间。它只是将接收到的输入写入发送到的缓冲区。如果输入比空间多,很可能会超出范围

另一方面,string是一个跟踪大小的容器,它将动态增长以适应输入

gets是一个彻底崩溃的函数。永远不要用它


编辑:正如James Kanze指出的,GET已经从C语言库中完全删除。

接口完全不同。在第一种情况下,内存缓冲区的大小是固定的,并且该大小不会传递给函数get,因此它无法控制其写入是否超出限制


在第二种情况下,内存缓冲区由std::string管理,函数将确保它根据需要增长。也就是说,std::字符串将增长到有足够的空间容纳整个输入。

gets不检查长度,因此您可以在不进行任何边界检查的情况下通过MAX_BUF,因为c/c++不进行边界检查。通常在编译时或运行时,您会收到一条关于get不安全的警告。您应该使用一个进行一些检查的函数。std::string将动态调整自身大小,以适应您放入其中的任何大小数据,因此它可能只是将MAX_BUF更改为更大的数字的问题。

与std::string不同,std::string通过引用传递给操作符>>,并且可以修改,BUF是固定的,并且通过指针传递。缓冲区只能容纳您分配的数据量,并且不能随着用户输入的大小而增长。gets不知道缓冲区的限制在哪里,因此它不检查缓冲区,可能是写入超过分配空间的末尾。这是一种未定义的行为,可利用该行为向内存中填充表示可执行代码的数据,以便恶意利用

如果签名是getschar**,GET的编写者可能需要malloc-ed空间并使用realloc扩展缓冲区;然而,考虑到当前指定API的方式,即使在理论上也无法修复溢出

这个问题非常严重,以至于C库的设计者决定在即将到来的语言标准中从标准库中删除GET。

gets reads,直到它找到一个“\n”。如果超过 一行中有最多个字符,它将继续写入 它们超出了缓冲区的末端。gets已被弃用 因为没有办法安全地使用它

cin>>s读取直到if找到空白,因此语义 都不一样,如果需要,将增长字符串。因为 它会增加缓冲区,它将永远不会读取超过
它。

s可以动态地增加其存储容量。buf不能。因为std::string可以增长以适应运行时确定大小的输入。哇,得到了很多分数。显然,这个问题应该是显而易见的:/我不理解这里的反对票:这对任何从管理内存访问的语言来到C/C++的人来说都不是显而易见的。如果输入比空间多,它很可能会超出界限啊,这是有道理的。我没有想到这一点。值得指出的是,GET实际上已经从C标准中删除,因为没有安全使用它的方法。当然,还有GETSys,但是C++解决方案工作得更好。