如果忽略返回值,如何提出警告?

Dra*_*sha 53 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;
}
Run Code Online (Sandbox Code Playgroud)

请注意:

  • 它应该工作,即使函数及其使用在不同的文件中
  • 免费静态检查工具

Eri*_*nen 54

你想要GCC的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;
}
Run Code Online (Sandbox Code Playgroud)

尝试编译此代码会产生:

$ gcc test.c
test.c: In function `main':
test.c:16: warning: ignoring return value of `f', declared with
attribute warn_unused_result
Run Code Online (Sandbox Code Playgroud)

你可以在Linux内核中看到这个; 他们有一个__must_check做同样事情的宏; 看起来你需要GCC 3.4或更高版本才能工作.然后你会发现内核头文件中使用的宏:

unsigned long __must_check copy_to_user(void __user *to,
                                        const void *from, unsigned long n);
Run Code Online (Sandbox Code Playgroud)

  • 在我的头文件中正常工作.我将一个带有WARN_UNUSED的函数原型放在一个新文件lib.h中,然后从test.c中包含它并得到相同的警告.另请注意,这是Linux内核的工作方式. (2认同)

小智 10

据我所知,没有GCC选项可以发出此警告.但是,如果您对特定功能感兴趣,可以使用以下属性标记它们:

int fn() __attribute__((warn_unused_result));
Run Code Online (Sandbox Code Playgroud)

如果没有使用fn()的返回值,它会发出警告.警告:我自己从未使用过此功能.


Joe*_*oeG 10

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

您不返回错误代码(例如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;
};
Run Code Online (Sandbox Code Playgroud)

  • 这是个好主意.不幸的是,它违反了"destructors must not throw"原则:http://www.parashift.com/c++-faq-lite/exceptions.html#faq-17.3,但也许可以接受"检查所有退货" "测试模式(可能不需要在最终版本构建中进行检查). (2认同)

Sha*_*our 9

对于C++ 17,这个问题的答案发生了变化,因为我们现在有了[[nodiscard]]属性.涵盖在[dcl.attr.nodiscard]中:

属性标记nodiscard可以应用于函数声明中的declarator-id或类或枚举的声明.它应该在每个属性列表中最多出现一次,并且不存在attribute-argument-clause.

[例如:

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
Run Code Online (Sandbox Code Playgroud)

 - 结束例子]

所以修改你的例子(现场直播):

[[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;
}
Run Code Online (Sandbox Code Playgroud)

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

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