我有这样的功能:
#include <setjmp.h>
jmp_buf buf;
void func2(int g);
extern int some_global;
void func(int x)
{
if (setjmp(buf))
return;
if (some_global)
x += 5;
func2(x);
}
GCC(gcc(Debian 4.4.5-8)4.4.5)发出警告:
test.c: In function ‘func’: test.c:5: warning: argument ‘x’ might be clobbered by ‘longjmp’ or ‘vfork’ [-Wclobbered]
为什么????我的意思是,显然我不在乎x
是否被破坏,因为在setjmp
返回后它不可能被使用。即使编译器应该知道一些非常明显的东西,因为它具有某种类setjmp
的特殊知识。
我的主要兴趣是找到我继承的代码库中的错误,因此,“使用这种编码风格”不是我正在寻找的建议。然而,这里有许多奇怪的曲折。例如,如果x
是局部变量而不是参数,那么GCC不会抱怨。此外,如果没有if (some_global)
行,GCC不会抱怨。尼斯。有些事情搞砸了GCC的流量分析,或者GCC知道我不知道的事情。
所以,
是否有一种简单的方法来抑制此功能的警告,就像将未使用的参数转换为(void)
一样?
或者我只是在项目范围内禁止警告?
或者我错过了什么?
更新:让我与您分享一个略微的不同版本,不会产生警告:
#include <setjmp.h>
jmp_buf buf;
void func2(int g);
extern int some_global;
void func(int y)
{
int x = y;
if (setjmp(buf))
return;
if (some_global)
x += 5;
func2(x);
}
答案 0 :(得分:12)
稍微刮网后,重新阅读GCC文档,我遇到了这个:
功能属性:
returns_twice
returns_twice
属性告诉编译器函数可能返回多次。编译器将确保在调用此类函数之前所有寄存器都已死,并将在第二次返回函数后发出有关可能被破坏的变量的警告。此类函数的示例包括setjmp
和vfork
。此类函数的longjmp
- 类似对应项(如果有)可能需要使用noreturn
属性进行标记。
因此,GCC似乎没有setjmp
的任何“特殊知识”,它只是暗示它确实存在。它只知道setjmp
返回两次,而不是它总是第一次返回0而后是非零。天哪,那本来不错。
答案 1 :(得分:6)
来自man longjmp
:
调用后,自动变量的值未指定 longjmp()如果符合以下所有条件:
· they are local to the function that made the corresponding setjmp(3)
call;
· their values are changed between the calls to setjmp(3) and
longjmp(); and
· they are not declared as volatile.
碰巧,第一个示例中的x
变量符合条件:
setjmp
为真,则some_global
之后可能会更改其值。因此,它的值可能未指定(已破坏)。
关于为什么第二个版本没有发出警告......不知道。