g++如何在忽略函数返回值时发出警告

33

lint 会产生一些警告,例如:

foo.c XXX Warning 534: Ignoring return value of function bar()

来自手册的lint警告:

534 忽略函数返回值

'Symbol' (与Location进行比较) 当一个返回值的函数只被用于其副作用时被调用,例如在语句本身中或逗号运算符的左侧。尝试使用 (void) function(); 来调用函数并忽略其返回值。另请参阅第5.5节 "标志选项"中的fvr、fvo和fdr标志。

我想在编译期间获取此警告(如果存在)。 gcc/g++中是否有任何选项可以实现这一点? 我已经打开了-Wall,但似乎没有检测到这个问题。

5个回答

34

自 C++17 开始,你可以使用 [[nodiscard]] 属性。

示例:


示例:
[[nodiscard]] int bar() {
  return 42;
}

1
也许值得一提的是,这仅意味着编译器被鼓励发出警告(没有保证)。 - ricab
2
在C++20中,您可以添加消息字符串:https://en.cppreference.com/w/cpp/language/attributes/nodiscard - Ciro Santilli OurBigBook.com

32

感谢WhirlWindpaxdiablo提供的答案和评论。以下是我尝试将这些片段组合成一个完整的 (?) 答案。

-Wunused-result 相关的gcc选项,默认已经打开。引用自gcc警告选项页面

-Wno-unused-result

如果调用标记了属性(请参见变量属性)的函数不使用其返回值,则不发出警告。默认值为-Wunused-result

因此,解决方法是在函数上应用warn_unused_result属性。

这里是一个完整的示例。文件unused_result.c的内容如下:

int foo() { return 3; }

int bar() __attribute__((warn_unused_result));
int bar() { return 5; }

int main()
{
    foo();
    bar();    /* line 9 */
    return 0;
}

以及相应的编译结果:

$gcc unused_result.c 
unused_result.c: In function ‘main’:
unused_result.c:9: warning: ignoring return value of ‘bar’, declared with attribute warn_unused_result

需要再次注意的是,-Wunused-result并不是必需的,因为它已经是默认设置。人们可能会想要明确表达这一意图,但在分析情况后,我选择不这样做。因为在编译选项中使用-Wunused-result可能会产生错误的安全/满足感,除非代码库中所有函数都有warn_unused_result的限定。


1
如果-Wunused-result是默认的,为什么编译器(gcc 9.2.1)没有警告我忽略了fgets的返回值? fgets最重要的目的之一是精确地将一个字节从流中返回,因此忽略它可能会有很大问题。 - m4l490n
1
@m4l490n 或许 fgets 没有被标记为“带有属性warn_unused_result”(也许应该这样做)? - nh2

9

8
关于使用__attribute__((warn_unused_result))的答案是正确的。然而,GCC在这个功能上表现不太好!请注意:它不会对非POD类型发出警告。这意味着,例如,如果您返回一个带有析构函数的类(或带有析构函数实例变量的类),您永远不会看到关于忽略结果的警告。
相关错误:https://gcc.gnu.org/bugzilla/show_bug.cgi?id=66177 失败的示例:
struct Error {
~Error();
};

__attribute__((warn_unused_result)) Error test();

int main()
{
    test();
    return 0;
}

因此,不要依赖于它来处理并不那么简单的返回类型。

1
一些其他相关的 Bugzilla:https://gcc.gnu.org/bugzilla/show_bug.cgi?id=38172 和 https://gcc.gnu.org/bugzilla/show_bug.cgi?id=46643 - pestophagous

-4

我是这样解决这个问题的:

#define ignore_result(x) if (x) {}

那么,不要使用(void)foo(),而是使用ignore_result(foo())

然后代码就可以很好地编译通过-Wall了。


OP的问题是可靠地获得警告而不是防止获得它。 - PRouleau

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