如何让gcc 4.7警告使用臭名昭著的gets()函数?

3
我看到了又一篇关于使用C语言的问题,其中代码中使用了gets()函数,我发表评论并警告说除了演示如何破解安全外,千万不要使用gets()函数。
这一次,我决定检查一下我的编译器是否会对使用gets()函数发出警告。当然,我认为应该会发出警告,是吧?即使你没有指定任何警告?
让我惊讶的是,我发现这个编译器不仅默认情况下没有发出警告,而且我甚至无法弄清如何让它发出警告!
这个问题的编译器是Debian上的gcc 4.7.2,以下是我使用的代码:
#include <stdio.h>

int main(void)
{
    char s[10];

    gets(s);
    puts(s);

    return 0;
}

尝试使用命令“gcc g.c”进行编译,未出现警告。运行后,如果输入太多的文本,则会导致段错误。
我还尝试了在Makefile中添加所有标准警告信息:
gcc -W -Wall -Wno-long-long -Wshadow -Wlarger-than-1000 \
-Wpointer-arith -Wbad-function-cast -Wcast-qual -Wcast-align \
-Wconversion -Waggregate-return -Wmissing-prototypes \
-Wmissing-declarations -Wpadded -Wredundant-decls -Wnested-externs g.c

同样的结果。

尝试使用-std=c11。即使这也没有产生警告,这是相当奇怪的,因为在C11中gets()甚至不存在。也尝试了c99。没有警告。

那么这里到底发生了什么?为什么当我使用整个C语言中最过时的函数时,这个被广泛使用的编译器不会警告我?


编辑:根据Keith Thompson的建议,我检查了stdio.h中是否有弃用属性。但是并没有。然后我复制了头文件并进行了实验。将这两个字符串中的任意一个(我在其他标头中找到的)添加到声明的末尾确实会生成警告:

__attribute_deprecated__
__attribute__ ((__deprecated__))

警告:
‘gets’ is deprecated (declared at /usr/include/stdiotz.h:632) [-Wdeprecated-declarations]

总结目前所见的回答,我的系统上的libc版本不包含警告,而在后续版本中有。这很奇怪,因为该警告至少从1996年以来就存在了某种形式。我模糊地记得,libc至少已经被分叉了一次,因此可能警告被留在一个分支中的时间比其他分支要晚得多。
我想我会在Debian邮件列表上询问这个问题,并根据我所学到的情况可能会报告它作为一个错误。
编辑2:我已经查看了一些源代码。glibc自2007年起至少在libio/iogets.c中有警告。我使用的eglibc 2.13正好有相同的警告代码:
#ifdef _LIBC
link_warning (gets, "the `gets' function is dangerous and should not be used.")
#endif

我猜测在编译该库时,_LIBC未被定义。为什么呢?我不知道。我也不确定_LIBC的目的是什么。

所以,答案似乎归结为“这是库,由于某些原因,在他们的智慧中,负责它的Debian开发者以那种方式进行了编译。”我们可能永远不会知道原因。

我不打算将其报告为错误,因为我正在使用旧版本。如果在我的下一次升级后仍然保持这种状态,我可能会提出来。

感谢大家提供有用的回复!


6
е°Ҷзј–иҜ‘еҷЁеҚҮзә§еҲ°GCC 5并дҪҝз”Ёgcc -Wall -Wextra -g -std=c11; жӮЁеҸҜиғҪиҝҳйңҖиҰҒеҚҮзә§жӮЁзҡ„libcпјҢиҝҷе®һйҷ…дёҠж„Ҹе‘ізқҖе°ҶLinuxеҸ‘иЎҢзүҲжӣҙж–°еҲ°иҫғж–°зҡ„зүҲжң¬гҖӮ - Basile Starynkevitch
任何gcc 4.6之后的版本,如果启用了警告,都会对gets函数发出警告,如上所述。 - David C. Rankin
1
@DavidC.Rankin,但这是gcc 4.7.2,即使使用Basile上面提供的一组标志,它也不会发出警告。 - Tom Zych
3
重点不在于编译器,而在于你的C库。GCC不包含C库。当前版本的glibc附带一个被注释为弃用属性的gets函数。(同时,在链接时还会出现一些问题,也会收到链接器的警告。) - Mat
1
我在使用gcc 4.8.4时收到了警告。/usr/include/stdio.h在其对gets的声明中具有__attribute_deprecated__。你的/usr/include/stdio.h是否也有这个? - Keith Thompson
显示剩余6条评论
1个回答

5

这个警告信息并不是GCC包含的,而是GLIBC。

你使用太老版本的GLIBC的可能性很小:这个警告信息至少从1996年就开始存在了。例如,可以看一下GitHub上的这段GLIBC代码中的第67行(注意日期:1996年12月15日):

link_warning (gets, "the `gets' function is dangerous and should not be used.")

很可能您正在使用不同的C库。


只是Debian安装的标准库,没有做任何特殊处理。而且安装时间不到两年。我想我应该向Debian报告这个问题。 - Tom Zych
gcc在glibc的stdio.h中响应注释而打印警告。 - Keith Thompson
@KeithThompson 实际上,gcc 打印了一个不同的警告 - 请参见我的编辑。也许有一个特殊的属性,比如__dangerous__,或者这是特别定制的代码。 - Tom Zych
编译器针对gets声明上的注释打印了一个警告,链接器产生了另一个不同的警告。 - Keith Thompson
似乎库就是以那种方式构建的,由于某种原因。请参见我对问题的第二次编辑获取详细信息。感谢您的回答。 - Tom Zych

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