C和C++安全编码(原书第2版)
上QQ阅读APP看书,第一时间看更新

2.5.3 C11附录K边界检查接口:gets_s()

C11的gets_s()函数是gets()的一个兼容且更安全的版本。

gets_s()函数是一个比fgets()更接近gets()函数的替代品,它只从stdin指向的流中读取,且不保留换行符。gets_s()函数接受一个额外的参数,rsize_t,用于指定输入的最大字符数。如果这个参数等于0或者比RSIZE_MAX更大,或者目标字符数组指针为NULL,将产生一个错误条件。如果产生了错误条件,那么将不会有任何的输入动作,并且目标字符数组将不会被更改。否则,该函数最多读入比指定数量少1的字符,并且在最后一个字符读入数组后立即在其后加上空字符。例2.11中所示的程序片段使用gets_s()函数从stdin中读取一行文本。

例2.11 使用gets_s()从stdin中读取


1  char buf[BUFSIZ];
2 
3  if (gets_s(buf, sizeof(buf)) == NULL) {
4    /* 
处理错误 */
5  }

如果gets_s()函数执行成功,则返回一个指向字符数组的指针。如果函数参数无效、遇到文件结束标志、没有字符被读入数组或者在读取过程中发生错误,则返回一个空指针。

只有当gets_s()函数读取一个完整的行(也就是说,它读取到一个换行符)时,它才执行成功。如果无法读取完整的行,该函数返回NULL,同时把缓冲区设置为空字符串,并清除输入流至下一个换行符。

如果指定的输入字符数超过目标缓冲区的长度,那么gets_s()函数仍然可能导致缓冲区溢出。

如前所述,fgets()函数允许正确编写的程序安全地处理太长而不能存储在结果数组的输入行。在一般情况下,这需要fgets()的调用者注意结果数组中是否存在一个换行字符。当使用gets_s()处理可能太长的输入行时,需要重写其运行约束处理程序(并在完成时,恢复它的默认值)。如果有任何基于换行符的处理需要,那么考虑使用fgets()而不是gets_s()。