1

在我的代码中,我使用以下行打印一个char readbuffer[1];数组(大小为 1 的 char 数组):

printf(readbuffer);

7.3.1+20180406-1这在我的电脑(Arch Linux,gcc 版本)上编译和工作没有问题。但是,当我将包含此代码的作业提交给我的导师时,他实际上在编译我的代码时收到了编译器警告:

shell.c:89:20: warning: format not a string literal and no format arguments [-Wformat-security]
         printf(readbuffer);

他正在使用 16.04 LTS 版本中的 gcc/clang 版本。我们都使用了相同的编译器标志。

为什么是这样?这在新gcc版本中突然不再是问题了吗?如果是这样,为什么不呢?

请注意:我不想知道如何解决此问题,而只想知道为什么警告与 gcc 版本不一致。

4

2 回答 2

2

我不想知道如何解决这个问题......

是的,你真的会!

除非您的char[1]变量始终包含\0,否则您正在做的事情是不安全的。和。如果它确实包含它,那么您所做的是什么:-)

做你想做的事情的正确方法是,假设需要printf

printf("%.1s", readbuffer);

这将确保您不会尝试阅读该单个字符。当然,如果您知道总会有一个字符,只需使用:

putchar(*readbuffer);

至于为什么不同gcc版本的报告不同,这可以归结为随着时间的推移而进行的简单改进。例如,这与为什么gcc会抱怨格式说明符数量和参数数量不匹配的原因相同,例如:

printf ("%s %d\n", "hello");

而其他一些实现可能不会。

具体来说,虽然该标准规定了必须报告为诊断的内容,但它并没有限制除此之外的实现可以报告为诊断的内容。

更高版本的编译器可能会添加或删除这些可选诊断,或者更改他们决定报告它们的方式。

于 2018-05-01T07:44:17.937 回答
1

这不是由 GCC 版本的差异引起的。相反,Ubuntu 已将 GCC 修改为-Wformat -Wformat-security默认启用. 如果你在 Arch Linux 上传递这些选项,你应该在那里看到相同的行为。

于 2018-05-01T06:46:33.007 回答