题
我想看看所有的地方,在我的代码(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)'.