使用gets函数防止缓冲区溢出

5
gets 的声明如下:
char * gets ( char * str );

请注意str的最大大小被明显省略了。 cplusplus.com表示:2

请注意,gets和fgets有很大的区别:gets不仅使用stdin作为源,而且在生成的字符串中不包括结束的换行符,并且不允许指定str的最大大小(这可能导致缓冲区溢出)。

此外:

C标准的最新修订版(2011年)已经从其规范中彻底删除了该函数。C++已经弃用该函数(自2011年标准开始,遵循C99+TC3)。

当然,现在常常推荐使用fgets来替代gets,因为它的声明看起来像这样:

char * fgets ( char * str, int num, FILE * stream );

确实需要一个尺寸参数,这使得它比gets更安全。

既然我不想花钱下载或购买C11标准,有人能否解释一下为什么废弃gets,以及对未来代码意味着什么?为什么fgets更安全却存在于相同的位置?而且为什么现在才开始废弃它?


4
N1570草案与发布的ISO C11标准几乎相同。 - Keith Thompson
@KeithThompson 谢谢您,先生。 - user3131113
1
我认为这个问题并非主要基于观点,因为C委员会已经解释了为什么gets被纳入标准。 - Yu Hao
2个回答

8

gets 已经被弃用,因为它是不安全的,正如您引述的那样,它可能会导致缓冲区溢出。C11 提供了一个替代方案 gets_s,它有这样一个签名:

char *gets_s(char *s, rsize_t n);

请注意,C11仍然建议使用fgets替换gets
首先,在标准中是否包含gets存在争议,但委员会决定当程序员对输入具有足够的控制时,gets是有用的。
以下是委员会的官方解释。

国际标准 - 编程语言C的原理 §7.19.7.7 The gets function:

因为gets不检查缓冲区溢出,所以在其输入不在程序员控制之下时,通常使用它是不安全的。这导致一些人质疑它是否应该出现在标准中。委员会决定,当程序员对输入具有足够的控制时,gets是有用和方便的,并且作为长期存在的实践,它需要一个标准规范。然而,总的来说,更喜欢的函数是fgets(参见§7.19.7.2)。


“gets_s” 并不普遍可用(这是轻描淡写的说法)。据我所知,它唯一可用的地方就是 Windows。 - S.S. Anne

2
现在由于我不想花钱下载或购买C11标准,有人能否解释一下废弃gets的原因以及对未来代码意味着什么?
根据C99标准的理由委员会:
由于gets函数没有检查缓冲区溢出,所以当其输入不在程序员的控制范围内时使用它是不安全的。这引起了一些人对它是否应该出现在标准中的质疑。委员会决定,在程序员确实可以充分控制输入的特殊情况下,gets函数是有用和方便的,并且作为长期存在的实践,它需要一个标准规范。然而,通常情况下,优选的函数是fgets。

n1570是最新的草案;在谷歌上搜索,你应该能够找到(合法的)下载链接。 - S.S. Anne

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接