18

我有这样的功能:

#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:在函数'func'中:
test.c:5:警告:参数“x”可能被“longjmp”或“vfork”破坏 [-Wclobbered]

为什么????我的意思是,显然我不在乎是否x被破坏,因为它不可能在setjmp返回后使用。考虑setjmp到它对.

我的主要兴趣是在我继承的代码库中查找错误,因此,“改用这种编码风格”不是我要寻找的建议。然而,这里有许多奇怪的曲折。例如,如果x是局部变量而不是参数,则 GCC 不会抱怨。此外,GCC 不会在没有if (some_global)线路的情况下抱怨。好的。有些东西搞砸了 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);
}
4

2 回答 2

15

在稍微刮了一下网,并重新阅读了 GCC 文档后,我发现了这个:

功能属性:

returns_twice

returns_twice属性告诉编译器一个函数可能返回不止一次。编译器将确保在调用此类函数之前所有寄存器都已失效,并将发出有关在函数第二次返回后可能被破坏的变量的警告。此类函数的示例是setjmpvfork。此类函数的longjmp-like 对应项(如果有)可能需要使用该noreturn属性进行标记。

因此,GCC 似乎没有任何“特殊知识” setjmp,它只是暗示它有。它所知道的只是setjmp返回两次,而不是第一次总是返回 0,之后总是返回非零。天哪,那会很好。

于 2011-10-12T01:24:32.527 回答
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为真,它的值可能会在之后更改。
  • 它不是易变的。

所以它的值可能是未指定的(破坏)。

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

于 2011-10-11T12:38:38.380 回答