C++ 如果忽略返回值,如何发出警告?
我希望看到我的代码(C++)中所有忽略函数返回值的地方。我如何做到这一点-使用gcc或静态代码分析工具 错误代码示例: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*
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结果
。