我想看看所有的地方,在我的代码(C++)无视返回值的一个函数。我怎么可以这样做-与海湾合作委员会或静态的代码分析工具?

糟糕代码的例子:

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;
}

请注意:

  • 它应工作,即使功能及其使用在不同的文件
  • 免费的 静态检查工具
有帮助吗?

解决方案

你想要海湾合作委员会的 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;
}

试图编纂这个代码生成:

$ gcc test.c
test.c: In function `main':
test.c:16: warning: ignoring return value of `f', declared with
attribute warn_unused_result

你可以看到这种使用在 Linux内核;他们有一个 __must_check 宏观,做同样的事情;看起来你需要的海湾合作委员会3.4或更大的这个工作。然后你会发现,宏用在核心标题的文件:

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

其他提示

作为我知道没有海湾合作委员会选择让这个警告。但是,如果你有兴趣的特定功能,可以标记他们有一个属性:

int fn() __attribute__((warn_unused_result));

这将得到一个警告,如果返回值fn()没有使用。警告:我从来没有使用这个功能自己。

你可以用这个方便的模板做到这一在运行时间。

而不是返回的一个错误代码(例如HRESULT)返回return_code<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;
};

C++17这个问题的答案变化,因为我们现在有 [[nodiscard]] 属性。复盖在 [dcl.attr。nodiscard]:

属性的令牌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

—结束例]

所以修改的例子(看到它的生活):

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


int main()
{
  int i = 7;
  f(i); // now we obtain a diagnostic

  return 1;
}

我们现在得到诊断与这两个海湾合作委员会和例如铛

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

任何静态的分析代码(例如 PC-棉绒)应该能告诉你。为PC-皮棉,我知道是这种情况。

静态分析将会为你做的工作,但是如果你的代码的基础是更多的那么微不足道准备被淹没;-)

静态分析将是你最好的选择在这里。我们使用Coverity在这里的,但也有 免费工具 可以,你可以使用。

如果你需要一个快速的和肮脏的解决方案和你有一个Linux风格的外壳的方便,可以尝试一些东西,如:

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

就会发现每一条线引用指定的功能,但并不包含"=".你可以得到一个很大的误报(和潜在的一些假阴性)但是,如果你没有一个静态分析这是一个体面的地方开始。

经典的'皮棉'使用的程序是非常健谈的有关职能,返回一个值得被忽略。麻烦的是,许多这些警告是不必要的领导以过度的噪音在棉绒出(这是捡位的绒毛,你想要它忽略).也许这就是为什么海湾合作委员会没有一个标准的警告。

其他问题的另一面-是"你怎么抑制警告当你知道你被忽略的结果,但真的不关心"。经典的情况是:

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

你关心的第一个结果 signal();你知道,第二次会SIG_IGN(因为你只是集到那)。远离的警告,我有时使用某些变体:

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

这将分配到 old 两倍。你可以跟着'assert(老==SIG_IGN)'.

许可以下: CC-BY-SA归因
不隶属于 StackOverflow
scroll top