setjmp 和 GCC 的合法用途

发布于 2024-10-10 22:55:28 字数 548 浏览 0 评论 0原文

使用 GCC(对我来说是 4.0)是合法的:

if(__builtin_expect(setjmp(buf) != 0, 1))
  {
    // handle error
  }
else
  {
    // do action
  }

我发现一个讨论说它在 2003 年给 GCC 带来了一个问题,但我想他们现在应该已经修复了它。 C 标准规定,使用 setjmp 是非法的,除非它是四个条件之一,相关的条件如下:

  • 关系运算符或相等运算符的一个操作数,另一个操作数是整数常量表达式,结果表达式是选择或迭代语句的整个控制表达式;

但如果这是一个 GCC 扩展,我能保证它可以在 GCC 下工作吗,因为它已经是非标准功能了?我测试了它,它似乎有效,尽管我不知道我需要做多少测试才能真正打破它。 (我将对 __builtin_expect 的调用隐藏在宏后面,该宏被定义为非 GCC 的无操作,因此对于其他编译器来说这是完全合法的。)

Using GCC (4.0 for me), is this legal:

if(__builtin_expect(setjmp(buf) != 0, 1))
  {
    // handle error
  }
else
  {
    // do action
  }

I found a discussion saying it caused a problem for GCC back in 2003, but I would imagine that they would have fixed it by now. The C standard says that it's illegal to use setjmp unless it's one of four conditions, the relevant one being this:

  • one operand of a relational or equality operator with the other operand an integer constant expression, with the resulting expression being the entire controlling expression of a selection or iteration statement;

But if this is a GCC extension, can I guarantee that it will work under for GCC, since it's already nonstandard functionality? I tested it and it seemed to work, though I don't know how much testing I'd have to do to actually break it. (I'm hiding the call to __builtin_expect behind a macro, which is defined as a no-op for non-GCC, so it would be perfectly legal for other compilers.)

如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。

扫码二维码加入Web技术交流群

发布评论

需要 登录 才能够评论, 你可以免费 注册 一个本站的账号。

评论(2

蘑菇王子 2024-10-17 22:55:28

我认为该标准所讨论的是考虑执行以下操作:

int x = printf("howdy");
if (setjmp(buf) != x ) {
    function_that_might_call_longjmp_with_x(buf, x);
} else {
    do_something_about_them_errors();
}

在这种情况下,您不能再依赖 x 拥有在上一行中分配的值。编译器可能已经移动了 x 所在的位置(重用它所在的寄存器,或者其他东西),因此进行比较的代码将在错误的位置查找。 (您可以将 x 保存到另一个变量,然后在调用函数之前将 x 重新分配给其他变量,这可能会使问题更加明显)

在您的代码中,您可以编写 我认为

int conditional;
conditional = setjump(buf) != 0 ;
if(__builtin_expect( conditional, 1)) {
    // handle error
} else {
    // do action
}

我们可以满足自己的要求,即分配变量 conditional 的代码行满足该要求。

I think that what the standard was talking about was to account for doing something like this:

int x = printf("howdy");
if (setjmp(buf) != x ) {
    function_that_might_call_longjmp_with_x(buf, x);
} else {
    do_something_about_them_errors();
}

In this case you could not rely on x having the value that it was assigned in the previous line anymore. The compiler may have moved the place where x had been (reusing the register it had been in, or something), so the code that did the comparison would be looking in the wrong spot. (you could save x to another variable, and then reassign x to something else before calling the function, which might make the problem more obvious)

In your code you could have written it as:

int conditional;
conditional = setjump(buf) != 0 ;
if(__builtin_expect( conditional, 1)) {
    // handle error
} else {
    // do action
}

And I think that we can satisfy ourselves that the line of code that assigns the variable conditional meets that requirement.

转身泪倾城 2024-10-17 22:55:28

但如果这是一个 GCC 扩展,我能保证它可以在 GCC 下工作吗,因为它已经是非标准功能了?我测试了它,它似乎有效,尽管我不知道我需要做多少测试才能真正打破它。 (我将对 __builtin_expect 的调用隐藏在宏后面,该宏被定义为非 GCC 的无操作,因此对于其他编译器来说这是完全合法的。)

你是对的, __builtin_expect 应该是其他编译器的宏无操作,因此结果仍然是定义的。

But if this is a GCC extension, can I guarantee that it will work under for GCC, since it's already nonstandard functionality? I tested it and it seemed to work, though I don't know how much testing I'd have to do to actually break it. (I'm hiding the call to __builtin_expect behind a macro, which is defined as a no-op for non-GCC, so it would be perfectly legal for other compilers.)

You are correct, __builtin_expect should be a macro no-op for other compilers so the result is still defined.

~没有更多了~
我们使用 Cookies 和其他技术来定制您的体验包括您的登录状态等。通过阅读我们的 隐私政策 了解更多相关信息。 单击 接受 或继续使用网站,即表示您同意使用 Cookies 和您的相关数据。
原文