这些破坏性变量警告有何意义?

时间:2011-10-11 05:48:27

标签: c gcc warnings longjmp

我有这样的功能:

#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);
}

2 个答案:

答案 0 :(得分:12)

稍微刮网后,重新阅读GCC文档,我遇到了这个:

功能属性:

  

returns_twice

     

returns_twice属性告诉编译器函数可能返回多次。编译器将确保在调用此类函数之前所有寄存器都已死,并将在第二次返回函数后发出有关可能被破坏的变量的警告。此类函数的示例包括setjmpvfork。此类函数的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之后可能会更改其值。
  • 不易挥发。

因此,它的值可能未指定(已破坏)。

关于为什么第二个版本没有发出警告......不知道。