gpt4 book ai didi

c - 如何规避 GCC 中的格式截断警告?

转载 作者:太空狗 更新时间:2023-10-29 16:47:19 32 4
gpt4 key购买 nike

我收到以下 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 的原因。有没有办法让编译器清楚地知道这是有意的(不使用 pragma 或 -Wno-format-truncation)?

最佳答案

  1. 警告是在 gcc7.1 中添加的,请参阅 gcc7.1 release changes .
  2. 来自 gcc docs :

Level 1 of -Wformat-truncation [...] warns only about calls to bounded functions whose return value is unused and that will most likely result in output truncation.

  1. 问题是 bug report并作为 NOTABUG 关闭:

Unhandled output truncation is typically a bug in the program. [...]
In cases when truncation is expected the caller typically checks the return value from the function and handles it somehow (e.g., by branching on it). In those cases, the warning is not issued. The source line printed by the warning suggests that this is not one of those cases. The warning is doing what it was designed to do.

  1. 但我们可以只检查 snprintf 的返回值,它在错误时返回负值。

#include <stdio.h>
#include <stdlib.h>
int main() {
char dst[2], src[2] = "a";

// snprintf(dst, sizeof(dst), "%s!", src); // warns

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 gcc8.1 使用 -O{0,1,2,3} -Wall -Wextra -pedantic。不给出任何警告。 gcc8.1 优化/删除了对 abort() 的调用,优化大于 -O1

奇怪的是,当编译为C++源文件时,即使我们检查返回值,警告仍然存在。在 C 中一切都很好。在 C++ 中更喜欢 std::format_to anyway .所以:

  1. 我们可以只使用编译器特定的语法来禁用警告。

#include <stdio.h>    
#include <stdlib.h>
int main() {
char dst[2];

char src[2] = "a";
// does not warn in C
// warns in C++ with g++ newer than 10.1 with optimization -O2
int ret = snprintf(dst, sizeof(dst), "%s!", src);
if (ret < 0) {
abort();
}

// does not warn in C
// still warns in C++
ret = snprintf(dst, sizeof(dst), "%s!", "a");
if (ret < 0) {
abort();
}

// use compiler specific pragmas to disable the warning
#pragma GCC diagnostic push
#pragma GCC diagnostic ignored "-Wformat-truncation"
snprintf(dst, sizeof(dst), "%s!", "a");
#pragma GCC diagnostic pop

// wrapper macro with compiler specific pragmas
// works for any gcc
// works from g++ 10.1
#ifndef __GNUC__
#define snprintf_nowarn snprintf
#else
#define snprintf_nowarn(...) __extension__({ \
_Pragma("GCC diagnostic push"); \
_Pragma("GCC diagnostic ignored \"-Wformat-truncation\""); \
const int _snprintf_nowarn = snprintf(__VA_ARGS__); \
_Pragma("GCC diagnostic pop"); \
_snprintf_nowarn; \
})
#endif
snprintf_nowarn(dst, sizeof(dst), "%s!", "a");
}

关于c - 如何规避 GCC 中的格式截断警告?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/51534284/

32 4 0
Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
广告合作:1813099741@qq.com 6ren.com