非零退出编译器提示



我想要

int some_opaque_error_handler() __attribute__((returns_nonzero));
^~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~^ equivalent of this

我使用的一个基于C/c++的库使用返回码来指示错误,这会导致编译器抱怨使用"unitalized";值。例如

int foo(int **ptr)
{
// detail not important here, just that:
// 1. compiler sees the contents of foo() from bar()
// 2. foo() has some kind of early return in error-path
// 3. precise return value of foo() from early return not known to the compiler
// 4. ptr is 100% properly initialized in non-error path (i.e. warning is 
//    indeed spurious)
if (ptr == 0xdeadbeef) {
return some_opaque_error_handler(...); // returns nonzero
}
*ptr = properly_initialize();
return 0;
}
int bar()
{
int *p;
if (foo(&p)) {
return /* continue propogating the error yadda yadda yadda */;
}
*p += 1; // Warning: p may be used uninitialized
}

在这种情况下,如果foo()返回错误,*p永远不会从bar()访问,但由于错误处理程序是不透明的,编译器无法知道这一点。

是否有办法让编译器知道通过错误处理返回的几乎总是[1]非零(因此任何后续访问都不会发生?)[2]。我在运行静态分析程序时也遇到了类似的问题,因为它们也假设执行可能会继续超过这些点。


[1]用户可以更改错误处理程序的行为-尽管不太可能-返回0,因此任何解决方案/编译器提示必须是非绑定的。

[2]是的,我知道我可以简单地初始化变量(,这是我目前所做的),但:

  1. 有一船这样的情况
  2. 这些警告似乎严重依赖于编译器、编译器版本、优化级别和土星环相对于银道面的方向

这感觉就像一场打地鼠游戏

如果你愿意使用宏,你可以把你的函数变成这样:

#define some_opaque_error_handler(...) 
(some_opaque_error_handler(__VA_ARGS__) ?: -1)

这依赖于一个GCC扩展,如果中间操作数不为零,则省略中间操作数给出测试值。


如果你想避免使用扩展,你可以将逻辑嵌入到内联函数中。

static inline int return_nonzero (int exp) {
return (exp ? exp : -1);
}
/* ... */
#define some_opaque_error_handler(...) 
return_nonzero(some_opaque_error_handler(__VA_ARGS__))

将该函数标记为写访问

__attribute__((__access__(__write_only__, 1)))
int foo(int **ptr) {

我想要int some_opaque_error_handler() __attribute__((returns_nonzero));

你可以这样做:

#define some_opaque_error_handler()  
__extension__({ 
int _x = some_opaque_error_handler(); 
if (_x == 0) __builtin_unreachable(); 
_x; 
})

或呼叫站点相同。

相关内容

  • 没有找到相关文章

最新更新