setjmp 和 longjmp 函数使用详解

在网上看到的,觉得很有用,copy过来的。

非局部跳转语句—setjmp和longjmp函数。非局部指的是,这不是由普通C语言goto,语句在一个函数内实施的跳转,而是在栈上跳过若干调用帧,返回到当前函数调用路径上的某一个函数中。

返回值:若直接调用则返回0,若从longjmp调用返回则返回非0值的longjmp中的val值

调用此函数则返回到语句setjmp所在的地方,其中env 就是setjmp中的 env,而val 则是使setjmp的返回值变为val。

当检查到一个错误时,则以两个参数调用longjmp函数,第一个就是在调用setjmp时所用的env,第二个参数是具有非0值的val,它将成为从setjmp处返回的值。使用第二个参数的原因是对于一个setjmp可以有多个longjmp。

上述程序将输出:

注意到虽然first()子程序被调用,”first“不可能被打印。”main“被打印,因为条件语句if ( ! setjmp(buf) )被执行第二次。

使用setjmp和longjmp要注意以下几点:

1、setjmp与longjmp结合使用时,它们必须有严格的先后执行顺序,也即先调用setjmp函数,之后再调用longjmp函数,以恢复到先前被保存的“程序执行点”。否则,如果在setjmp调用之前,执行longjmp函数,将导致程序的执行流变的不可预测,很容易导致程序崩溃而退出

2.  longjmp必须在setjmp调用之后,而且longjmp必须在setjmp的作用域之内。具体来说,在一个函数中使用setjmp来初始化一个全局标号,然后只要该函数未曾返回,那么在其它任何地方都可以通过longjmp调用来跳转到 setjmp的下一条语句执行。实际上setjmp函数将发生调用处的局部环境保存在了一个jmp_buf的结构当中,只要主调函数中对应的内存未曾释放 (函数返回时局部内存就失效了),那么在调用longjmp的时候就可以根据已保存的jmp_buf参数恢复到setjmp的地方执行。

异常处理

在下例中,setjmp被用于包住一个例外处理,类似trylongjmp调用类似于throw语句,允许一个异常返回给setjmp一个异常值。下属代码示例遵从1999 ISO C standardSingle UNIX Specification:仅在特定范围内引用setjmp

  • ifswitch或它们的嵌套使用的条件表达式
  • 上述情况下与!一起使用或者与整数常值比较
  • 作为单独的语句(不使用其返回值)

遵从上述规则使得创建程序环境缓冲区更为容易。更一般的使用setjmp可能引起未定义行为,如破坏局部变量;编译器被要求保护或警告这些用法。但轻微的复杂用法如switch ((exception_type = setjmp(env))) { }在文献与实践中是常见的,并保持了相当的可移植性。

1 3 收藏 评论

相关文章

可能感兴趣的话题



直接登录
跳到底部
返回顶部