我正在Unix中使用C编程,我正在使用gets
读取键盘输入。然而,我总是收到这个警告并且程序停止运行:
warning: this program uses gets(), which is unsafe.
有人能告诉我为什么会发生这种情况吗?
我正在Unix中使用C编程,我正在使用gets
读取键盘输入。然而,我总是收到这个警告并且程序停止运行:
warning: this program uses gets(), which is unsafe.
有人能告诉我为什么会发生这种情况吗?
gets
是不安全的,因为你给它一个缓冲区,却没有告诉它这个缓冲区有多大。输入可能会写过缓冲区的末尾,导致程序出现非常严重的问题。使用fgets
会好一些,因为你可以告诉它缓冲区有多大,像这样:
const int bufsize = 4096; /* Or a #define or whatever */
char buffer[bufsize];
fgets(buffer, bufsize, stdin);
...所以只要您提供正确的信息,它就不会在缓冲区末尾写入并破坏事物。
略有偏差,但:
您不必为缓冲区大小使用const int
,但我强烈建议您不要仅在两个位置都放置文字数字,因为不可避免地您将稍后更改一个但不更改另一个。编译器可以提供帮助:
char buffer[4096];
fgets(buffer, (sizeof buffer / sizeof buffer[0]), stdin);
那个表达式在编译时被解析,而不是运行时。打这个表达式很痛苦,所以我过去在我的头文件中使用宏:
#define ARRAYCOUNT(a) (sizeof a / sizeof a[0])
......但我的纯C知识已经过时几年了,现在可能有更好的方法。
char
数组,就没有必要除以sizeof buffer[0]
,因为根据定义sizeof(char)==1
,也就是说函数调用可以简化为fgets(buffer,sizeof buffer,stdin)
。 - Christophchar
在所有平台上都是一个字节,或者如果它是(比如)两个字节,那么fgets
的缓冲区大小参数将被应用为字符而不是字节吗?我见过的大多数文档都说是字节。我已经有一段时间没有玩C语言了,我知道这些东西变得更加复杂了,所以我在代码中有点防御性。但是,是的,@OP,如果这些假设是安全的,那么您可以省略使用char
数组进行计算(但是对于int
、long
等类似习惯用法的应用不行)。 - T.J. Crowderchar
为1字节。 - jamesdlinsizeof(char)
始终为1。 - Christoph如前面的答案所提到的,使用fgets
代替gets
。
但并不是说gets
完全不能用,它只是非常非常不安全。我猜测你的代码中可能有一个错误,即使使用fgets
也会出现这个问题,请把你的源代码发布出来。
编辑 根据您在评论中提供的更新信息,我有几个建议。
I recommend searching for a good C tutorial in your native language, Google is your friend here. As a book I would recommend The C Programming Language
If you have new information it is a good idea to edit them into your original post, especially if it is code, it will make it easier for people to understand what you mean.
You are trying to read a string, basically an array of characters, into a single character, that will of course fail. What you want to do is something like the following.
char username[256];
char password[256];
scanf("%s%s", username, password);
Feel free to comment/edit, I am very rusty even in basic C.
编辑2 正如jamesdlin所警告的那样,使用scanf
和gets
一样危险。
scanf
用法和 gets
一样糟糕。(也要避免使用 scanf
:http://c-faq.com/stdio/scanfprobs.html) - jamesdlinman gets
说:
永远不要使用gets()。因为在不知道数据大小的情况下,无法确定gets()将读取多少个字符,并且由于gets()会继续存储超出缓冲区末尾的字符,因此使用它非常危险。它已被用来破坏计算机安全。请改用fgets()。
gets() 是不安全的。它只接受一个参数,即指向 char 缓冲区的指针。请考虑需要将缓冲区大小设置为多大以及用户输入时可以在未按回车键的情况下输入多长时间。
基本上,使用 gets() 无法防止缓冲区溢出 - 应该使用 fgets()。
scanf
。为什么您会感到惊讶,程序然后“停止”呢? - AnT stands with Russiauser
和pass
需要声明为char数组,而不是单个字符。"%s"转换说明符期望相应的参数具有类型char *
,并且该参数需要指向一个足够长的缓冲区,以容纳输入字符串加上0终止符(未装饰的"%s"转换说明符在这方面暴露了与gets()
相同的安全漏洞,但这里没有足够的空间详细讨论)。将user
和pass
的声明更改为char user[N]; char pass[M]
,其中N和M是您需要的两个数组的大小。 - John Bode