我在我的 C 代码中使用函数
gets()
。
我的代码工作正常,但我收到一条警告消息
(.text+0xe6): warning: the `gets' function is dangerous and should not be used.
我希望不要弹出此警告消息。有什么办法吗
我想知道通过创建一个头文件来禁用某些警告是否可能存在这种可能性。或者编译过程中是否有任何选项可以满足我的目的?或者可能有一种特殊的方法可以使用
gets()
来避免弹出此警告?
显而易见的答案是从编译器试图告诉你的内容中学习 - 你永远不应该使用 gets(),因为它完全不安全。请改用 fgets(),这样可以防止可能的缓冲区溢出。
#define BUFFER_SIZE 100
char buff[BUFFER_SIZE];
gets( buff); // unsafe!
fgets( buff, sizeof(buff), stdin ); // safe
如果你真的想用它。
这是答案来自:http://www.gamedev.net/community/forums/topic.asp?topic_id=523641
如果您使用最新版本的 gcc,您可以使用:
#pragma GCC diagnostic ignored "your option here"
例如,如果这些标头产生“浮点比较不安全”错误,您可以使用:
#pragma GCC diagnostic ignored "-Wfloat-equal".
不幸的是,您不能以这种方式禁用“-Wall”(这太简单了,不是吗...),您必须手动执行 -Wall 启用的各个警告选项(至少是冲突的选项) .
文档:http://gcc.gnu.org/onlinedocs/gcc/Diagnostic-Pragmas.html#Diagnostic-Pragmas
编辑: 但它似乎不适用于收到警告...我在我的电脑上尝试过。
使用 fgets() 代替 gets()
char buffer[BUFSIZ];
/* gets(buffer); */
fgets(buffer,sizeof(buffer), stdin);
gets() 函数不检查缓冲区的长度,并且可以写入超过末尾并更改堆栈。这就是您听到的“缓冲区溢出”。
我会留意警告并更换
gets
。这对我来说已经很清楚了:
错误
永远不要使用 gets()。 因为如果不知道里面的数据就无法判断 提前 gets() 将读取多少个字符,并且因为 gets() 将继续存储 字符超过缓冲区末尾,使用起来极其危险。 它有 被用来破坏计算机安全。 使用 fgets() 代替。
确实没有充分的理由使用
gets()
。甚至 C 标准也说它已经过时了!请使用 fgets()
来代替。
[编辑]
看起来警告来自链接器。使用
-c
编译时是否收到警告? (这会禁用链接。)
-fno-stack-protector
是一个允许使用 gets()
功能的选项,尽管它是多么不安全。
-Wno-deprecated-declarations
关闭弃用警告
这是使用
gets()
进行编译的示例
gcc myprogram.c -o myprogram -fno-stack-protector -Wno-deprecated-declarations
我同意每个人的观点,即它完全不安全,因为它会允许程序溢出缓冲区。这可能非常危险,因此它已被弃用,取而代之的是 fgets。
但是,如果您正在学习安全性课程,那么能够编写一个小型测试程序来研究缓冲区溢出和堆栈溢出的概念是非常有帮助的。
建议使用
gets()
的安全替代品。
在现有代码中,要替换
gets()
,可能不需要使用 fgets()
,因为该函数需要额外的 char
来保存两个函数消耗的 '\n'
,但 gets()
不会保存。 以下是不需要更大缓冲区大小的替代方案。
每个
gets(dest)
替换为:dest
是数组,则使用 gets_sz(dest, sizeof dest)
dest
是指向大小为 char
的 n
数组的指针,请使用 gets_sz(dest, n)
char *gets_sz(char *dest, size_t size) {
if (size <= 1) {
// If no room to save anything or stdin is at EOF ...
if (size == 0 || feof(stdin)) {
return NULL;
}
}
size--;
size_t i;
for (i = 0; i < size; i++) {
int ch = getchar();
if (ch == EOF) {
if (i == 0) {
return NULL;
}
break;
}
if (ch == '\n') {
break;
}
dest[i] = (char) ch;
}
dest[i] = 0;
return dest;
}
[编辑 2024]
修复了一些小问题,但 10 年后我认为应该改变更多 - 稍后会更多。
如果你真的想使用它,请尝试该标志
-fsyntax-only
。
gcc网站中的手册说:
-fsyntax-only
Check the code for syntax errors, but don't do anything beyond that.
与流行的观点相反,并非所有程序员都同样不专心于他们所写的内容。
gets()
将始终是 C90 中的标准,并且出于几个充分的原因将其放入库中。 如果使用得当,例如在程序示例、文档、单元测试脚手架、家庭作业等中,它并不比任何其他字符串函数更“危险”。
更重要的是,
gets()
以 fgets()
永远不会的方式增强了可读性。 人们永远不必打断自己的思路来查找其论点的顺序。
以下解决方法使用我最喜欢的另一个函数来删除换行符。 :)
#define gets GET_LOST
#include "stdio.h"
#undef gets
#include "limits.h"
char *gets(char *s)
{
return strtok(fgets(s, INT_MAX, stdin), "\n");
}