如果返回值被忽略,如何提出警告?
我想看看我的代码中的所有地方(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; }
请注意:
- 即使该function及其用途在不同的文件中也应该起作用
- 免费的静态检查工具
你想要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; }
试图编译这个代码产生:
$ 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
macros来做同样的事情; 看起来像你需要GCC 3.4或更高的工作。 然后你会发现在内核头文件中使用的macros:
unsigned long __must_check copy_to_user(void __user *to, const void *from, unsigned long n);
据我所知,没有GCC选项给这个警告。 但是,如果您对特定function感兴趣,则可以使用以下属性对它们进行标记:
int fn() __attribute__((warn_unused_result));
如果没有使用fn()的返回值,会发出警告。 警告:我从来没有使用过这个function。
你可以使用这个方便的模板在运行时做到这一点。
您将返回一个return_code <HRESULT>,而不是返回错误代码(例如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; };
任何静态分析代码(如PC-Lint )都应该能够告诉你。 对于PC-Lint,我知道这是事实。
一个静态分析器会为你做这个工作,但是如果你的代码基础更为微不足道的准备被压倒;-)
静态分析仪将是你最好的select。 我们在这里使用Coverity,但也有可用的免费工具 。
如果你需要一个快速而又脏的解决scheme,并且你有一个Linux风格的shell,你可以尝试如下的东西:
grep -rn "function_name" * | grep -v "="
这将find每一行引用指定的function,但不包含“=”。 你可以得到很多误报(可能会有一些误报),但是如果你没有静态分析器,那么这是一个不错的开始。
经典的“lint”程序过去常常会返回一个被忽略的值。 麻烦的是,许多这些警告是不必要的 – 导致皮棉输出过度的噪音(它正在捡起一些你想忽略的绒毛)。 这可能是为什么海湾合作委员会没有一个标准的警告。
另一个问题 – 另一方面 – 是“当你知道自己忽略了结果但是真的不在乎时,你怎么压制这个警告”。 经典的情况是:
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(old == SIG_IGN)'来实现。