Warning: file_get_contents(/data/phpspider/zhask/data//catemap/6/cplusplus/129.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
C++ 如果忽略返回值,如何发出警告?_C++_C_Gcc_Static Analysis - Fatal编程技术网

C++ 如果忽略返回值,如何发出警告?

C++ 如果忽略返回值,如何发出警告?,c++,c,gcc,static-analysis,C++,C,Gcc,Static Analysis,我希望看到我的代码(C++)中所有忽略函数返回值的地方。我如何做到这一点-使用gcc或静态代码分析工具 错误代码示例: int f(int z) { return z + (z*2) + z/3 + z*z + 23; } int main() { int i = 7; f(i); ///// <<----- here I disregard the return value return 1; } intf(intz){ 返回z+(z*2)+z/3+z*

我希望看到我的代码(C++)中所有忽略函数返回值的地方。我如何做到这一点-使用gcc或静态代码分析工具

错误代码示例:

int f(int z) {
    return z + (z*2) + z/3 + z*z + 23;
}


int main()
{
  int i = 7;
  f(i); ///// <<----- here I disregard the return value

  return 1;
}
intf(intz){
返回z+(z*2)+z/3+z*z+23;
}
int main()
{
int i=7;

f(i);//p>任何静态分析代码(例如)应该能够告诉您。对于PC Lint,我知道情况就是这样。

静态分析器将为您完成这项工作,但如果您的代码库过于琐碎,请准备好不知所措;-)

据我所知,没有GCC选项给出此警告。但是,如果您对特定函数感兴趣,可以使用属性:

int fn() __attribute__((warn_unused_result));
#define WARN_UNUSED __attribute__((warn_unused_result))

int WARN_UNUSED f(int z) {
    return z + (z*2) + z/3 + z*z + 23;
}

int main()
{
  int i = 7;
  f(i); ///// <<----- here i disregard the return value
  return 1;
}

如果未使用fn()的返回值,则会发出警告。警告:我本人从未使用过此功能。

静态分析器将是您在此处的最佳选择。我们在此处使用Coverity,但您也可以使用它

如果您需要一个快速而肮脏的解决方案,并且手边有一个Linux风格的shell,您可以尝试以下方法:

grep -rn "function_name" * | grep -v "="

这将找到引用指定函数但不包含“=”的每一行。您可能会得到很多误报(可能还有一些误报),但如果您没有静态分析器,这是一个不错的起点。

您想要GCC的
warn\u unused\u result
属性:

int fn() __attribute__((warn_unused_result));
#define WARN_UNUSED __attribute__((warn_unused_result))

int WARN_UNUSED f(int z) {
    return z + (z*2) + z/3 + z*z + 23;
}

int main()
{
  int i = 7;
  f(i); ///// <<----- here i disregard the return value
  return 1;
}
您可以在中看到这一点;他们有一个执行相同操作的
\u must\u check
宏;看起来您需要GCC 3.4或更高版本才能工作。然后您将在内核头文件中找到该宏:

unsigned long __must_check copy_to_user(void __user *to,
                                        const void *from, unsigned long n);

您可以使用这个方便的模板在运行时执行此操作

返回返回的不是错误代码(例如HRESULT),而是返回一个返回_代码,该代码断言它是否超出范围而没有读取值。它不是一个静态分析工具,但仍然很有用

class return_value
{
public:
  explicit return_value(T value)
    :value(value), checked(false)
  {
  }

  return_value(const return_value& other)
    :value(other.value), checked(other.checked)
  {
    other.checked = true;
  }

  return_value& operator=(const return_value& other)
  {
    if( this != &other ) 
    {
      assert(checked);
      value = other.value;
      checked = other.checked;
      other.checked = true;
    }
  }

  ~return_value(const return_value& other)
  {
    assert(checked);
  }

  T get_value()const {
    checked = true;
    return value;
  }

private:
  mutable bool checked;
  T value;
};

经典的“lint”程序过去常常对返回被忽略值的函数喋喋不休。问题是,许多警告都是多余的——导致lint输出中出现过多噪音(它拾取了一些您希望它忽略的绒毛)。这可能是GCC没有标准警告的原因

另一个问题——另一方面——是“当你知道你忽略了结果但真的不在乎时,你如何抑制警告”。这方面的经典场景是:

if (signal(SIGHUP, SIG_IGN) != SIG_IGN)
    signal(SIGHUP, sighandler);
您关心的是
signal()
的第一个结果;您知道第二个结果将是SIG\u IGN(因为您刚刚将其设置为SIG\u IGN)。为了避免出现警告,我有时会在:

if ((old = signal(SIGHUP, SIG_IGN)) != SIG_IGN)
    old = signal(SIGHUP, sighandler);

这两次都分配给
old
。您可以使用“assert(old==SIG_IGN)”来遵循这一点。

对于C++17,这个问题的答案会发生变化,因为我们现在有了该属性。在:

属性标记nodiscard可以应用于函数声明中的声明器id,也可以应用于类或枚举的声明。它在每个属性列表中最多出现一次,并且不应出现属性参数子句

[ 例如:

struct [[nodiscard]] error_info { /* ... */ };
error_info enable_missile_safety_mode();
void launch_missiles();
void test_missiles() {
  enable_missile_safety_mode(); // warning encouraged
  launch_missiles();
}
error_info &foo();
void f() { foo(); }             // warning not encouraged: not a nodiscard call, because neither
                                // the (reference) return type nor the function is declared nodiscard
 — 结束示例 ]

因此,修改示例():

我们现在获得gcc和clang的诊断结果,例如

warning: ignoring return value of function declared with 'nodiscard' attribute [-Wunused-result]
  f(i); // now we obtain a diagnostic
  ^ ~

例如,如果您使用
printf
,这将打印大量警告。无法通过命令行强制执行该命令的“可能”原因是,如果您有有效的理由忽略结果,则最终需要分配“未使用的变量”这将生成一个警告。例如,您当然不希望
t&operator=(t rhs);
强迫您捕获结果;@Matthieu M:当您想要忽略函数的返回值时,您不需要分配伪变量。只需将函数调用强制转换为void,如
(void)function\u returning\u a\u val()阅读代码时,这也清楚地表明您有意忽略返回值。
[[nodiscard]]
在C++17中。因为这看起来是关于这个主题的最古老、投票最多的问题,所以我添加了一个更新答案,涵盖C++17。实际上,这是说“不,我真的不在乎返回值”的典型方式转换为
void
,例如
(void)printf(“Hello,world!\n”);
即使在最高警告级别,也不会对此发出警告,并显式转换为void。是的,“
(void)
“cast可以工作……但是它在代码中看起来很难看。我必须注意用“
VOID
”替换难看的gram的代码;它映射到使用标准C编译器进行的“
(VOID)
”cast(现在都是C编译器),但起源于它们成为标准的前几天,然后将结果分配给一个文件静态变量(“
”define VOID“\u VOID=
”或诸如此类)。啊;必须跳过的内存和环。这是个好主意。不幸的是,它违反了“析构函数不能抛出”的规定原则:,但对于“检查所有返回”测试模式来说,这可能是可以接受的(在最终版本构建中可能不需要检查)。我见过使用最重要的错误代码位而不是
bool
的实现。对我来说,它在头文件中工作得很好。我在一个新的文件lib.h中放入了一个带有WARN_UNUSED的函数原型,然后从test.c中包含了该原型,并得到了相同的警告。另外请注意,Linux内核就是这样做的。关于此附件的更多详细信息可以在正式的gcc文档中找到该属性。
6.33.1通用函数属性----------------------
。安装
gcc文档
apt软件包,以便在gcc文档中轻松导航。拥有该软件包后,只需使用info读取
$info gcc
,并在索引搜索中搜索
警告未使用的\u结果