如何在GCC中规避格式截断警告?

时间:2018-07-26 08:26:35

标签: c gcc format gcc-warning

我收到以下gcc格式截断警告:

test.c:8:33: warning: ‘/input’ directive output may be truncated writing 6 bytes into a region of size between 1 and 20 [-Wformat-truncation=]
snprintf(dst, sizeof(dst), "%s-more", src);
                             ^~~~~~
test.c:8:3: note: ‘snprintf’ output between 7 and 26 bytes into a destination of size 20
snprintf(dst, sizeof(dst), "%s-more", src);
^~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~

关于这样的代码:

char dst[20];
char src[20];
scanf("%s", src);
snprintf(dst, sizeof(dst), "%s-more", src);
printf("%s\n", dst);

我知道它可能会被截断-但这正是我首先使用snprintf的原因。有没有一种方法可以使编译器清楚这是预期的(不使用编译指示或-Wno-format-truncation)?

5 个答案:

答案 0 :(得分:9)

  1. 警告已侵入gcc7.1,请参见gcc7.1 release changes
  2. 来自gcc docs
  

-Wformat-truncation [...]的级别1仅警告对有界函数的调用,这些函数的返回值未使用,并且很可能导致输出截断。

  1. 问题是一个bug report,并以NOTABUG的形式关闭:
  

未处理的输出截断通常是程序中的错误。 [...]
  在需要截断的情况下,调用方通常会检查该函数的返回值并以某种方式进行处理(例如,通过在其上分支)。在这种情况下,不会发出警告。警告显示的源代码行表明这不是这些情况之一。该警告正在执行其预期的操作。

  1. 但是我们只能检查snprintf的返回值,该值会在错误时返回负值。

#include <stdio.h>
#include <stdlib.h>
void f(void) {
    char dst[2], src[2];
    // snprintf(dst, sizeof(dst), "%s!", src);

    int ret = snprintf(dst, sizeof(dst), "%s!", src);
    if (ret < 0) {
         abort();
    }

    // But don't we love confusing one liners?
    for (int ret = snprintf(dst, sizeof(dst), "%s!", src); ret < 0;) exit(ret);
    // Can we do better?
    snprintf(dst, sizeof(dst), "%s!", src) < 0 ? abort() : (void)0;
    // Don't we love obfuscation?
#define snprintf_nowarn(...) (snprintf(__VA_ARGS__) < 0 ? abort() : (void)0)
    snprintf_nowarn(dst, sizeof(dst), "%s!", src);
}

https://godbolt.org/上使用gcc7.1 gcc7.2 gcc7.3在-O{0,1,2,3} -Wall -Wextra -pedantic上使用gcc8.1进行了测试。不发出任何警告。 gcc8.1使用大于abort()的优化来优化/删除对-O1的调用。

答案 1 :(得分:3)

您可以添加精度说明符。这将从src中最多打印14个字符,避免格式字符串可能被截断,并且不会触发该警告:

snprintf(dst, sizeof(dst), "%.14s-more", src);

online compiler

答案 2 :(得分:0)

仅当调用了受长度限制的*printf函数(snprintfvsnprintf)时才会触发此错误。换句话说,这并不表示您可能正在写入未分配的内存,就像sprintf可能发生的那样。它只会通知您snprintf可能正在工作和被截断时没有注意。

知道这一点,我更愿意使用-Wno-format-truncation在全局禁用它,而不是试图哄骗gcc忽略特定实例。

答案 3 :(得分:0)

这个页面对我很有用:
https://www.fluentcpp.com/2019/08/30/how-to-disable-a-warning-in-cpp/

您可以通过执行以下操作来解决 gcc/clang 编译器的问题:

#pragma GCC diagnostic push
#pragma GCC diagnostic ignored "-Wformat-truncation"
    snprintf(dst, sizeof(dst), "%s-more", src);
#pragma GCC diagnostic pop

上面的网页也有针对 Visual Studio 编译器警告的解决方案。

答案 4 :(得分:-1)

今天在带有附加gcc标志的项目中陷入错误。必须注释掉format=2

检查-Wformat=