首页
学习
活动
专区
圈层
工具
发布
社区首页 >问答首页 >如何安全地获得setjmp的返回值

如何安全地获得setjmp的返回值
EN

Stack Overflow用户
提问于 2014-04-06 11:08:49
回答 2查看 874关注 0票数 5

我希望使用longjmp返回一个错误代码,并从名为setjmp的函数中传递它。简化代码:

代码语言:javascript
复制
int do_things(stuff ........)
{
 int error_code;
 jmp_buf jb;

 if ((error_code = setjmp(jb)) == 0) {
    /* do stuff */
    return 0;
 }
 else {
    return error_code;
 }
}

但我读到:“对setjmp宏的调用只能出现在以下情况之一:

代码语言:javascript
复制
 the entire controlling expression of a selection or iteration statement

if (setjmp(jb)) {
switch (setjmp(jb)) {
while (setjmp(jb)) {

代码语言:javascript
复制
 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

if (setjmp(jb) < 3) {

代码语言:javascript
复制
 the operand of a unary ! operator with the resulting
 expression being the entire controlling expression of a
 selection or iteration statement

if (!setjmp(jb)) {

代码语言:javascript
复制
 the entire expression of an expression statement (possibly cast to void).

setjmp(bf); 

是否有一种获得返回值的好方法?(不使用switch,并为所有可能的值编写一个case )

编辑

感谢马特在c99的基本原理中找到了它。我现在想出来的是:

代码语言:javascript
复制
int do_things(stuff ........)
{
  volatile error_code;
  jmp_buf jb;

  if (setjmp(jb) == 0) {
     working_some(&error_code, ....);
     working_again(&error_code, ....);
     working_more(&error_code, ....);
     working_for_fun(&error_code, ....);
     return 0;
  }
  else {
     general_cleanup();
     return error_code;
  }
}

再多一个变量,看起来不太好.

EN

回答 2

Stack Overflow用户

回答已采纳

发布于 2014-04-06 11:32:38

来自C99原理

对setjmp提出的一个要求是,它与任何其他函数一样是可用的,也就是说,它在任何表达式上下文中都是可调用的,并且表达式正确地计算来自setjmp的返回是直接的还是通过对longjmp的调用。不幸的是,setjmp作为常规调用函数的任何实现都无法充分了解调用环境,无法保存通过表达式计算部分方式使用的任何临时寄存器或动态堆栈位置。( setjmp宏似乎只有在扩展到内联程序集代码或调用特定内置函数时才有所帮助。)在对setjmp的初始调用中,临时程序可能是正确的,但不太可能是在由对longjmp的相应调用启动的任何返回时。这些注意事项决定了这样一个约束,即setjmp只能在相当简单的表达式中调用,而这些表达式不可能需要临时存储。 C89委员会考虑的另一项建议是要求实现承认调用setjmp是一个特例,因此它们采取一切必要的预防措施,以便在长调用时适当地恢复setjmp环境。这项建议以一致性为由被拒绝:目前允许实现库功能,但没有其他情况需要特殊处理。

我对此的解释是,人们认为a = setjmp(jb);必须工作是过于严格的。所以标准没有定义。但是,特定的编译器可能会选择支持这一点(并且希望能够将其记录在案)。为了便于移植,我想您应该使用一些预处理器检查来验证代码是用已知的支持该代码的编译器编译的。

票数 3
EN

Stack Overflow用户

发布于 2014-04-06 11:15:16

POSIX.1确实指定了这些限制。但是,在Linux上,setjmp(3)没有提到它们,所以在这个平台上您可以简单地这样做:

代码语言:javascript
复制
int retval = setjmp(jb);

当然,这是以一些可移植性为代价的,但我不知道它有多糟糕。

票数 0
EN
页面原文内容由Stack Overflow提供。腾讯云小微IT领域专用引擎提供翻译支持
原文链接:

https://stackoverflow.com/questions/22893178

复制
相关文章

相似问题

领券
问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档