【转载】setjmp和longjmp函数使用详解

【说明】本文上半部分转载自 wykwdy007 的转载文章 http://blog.csdn.net/wykwdy007/article/details/6535322

--------------------------------------------------

非局部跳转语句---setjmp和longjmp函数。非局部指的是,这不是由普通C语言goto,语句在一个函数内实施的跳转,而是在栈上跳过若干调用帧,返回到当前函数调用路径上的某一个函数中。
#include <setjmp.h>
Int setjmp(jmp_buf  env);
   返回值:若直接调用则返回0,若从longjmp调用返回则返回非0值
Void longjmp(jmp_buf env,int val);
    在希望返回到的位置调用setjmp,此位置在main函数中,因为直接调用该函数,所以其返回值为0.setjmp参数evn的类型是一个特殊的类型jmp_buf,这一数据类型是某种形式的数组,其中存放在调用longjmp时能用来恢复栈状态的所有信息。因为需要在另一个函数中引用env变量,所以规范的处理方式是将env变量定义为全局变量。
   当检查到一个错误时,则以两个参数调用longjmp函数,第一个就是在调用setjmp时所用的env,第二个参数是具有非0值的val,它将成为从setjmp处返回的值。使用第二个参数的原因是对于一个setjmp可以有多个longjmp。
    下面我们可以看一个简单的例子:


#include <stdio.h>
#include <stdlib.h>
#include <setjmp.h>
#include <string.h>

void fun1(void);
void fun2(void);
 jmp_buf jmpbuffer;
void main(void)
{
    int i = 0;
    int j = 0;
    i = setjmp(jmpbuffer);
    if(i==0)
    {
        printf("first run/n");
        fun1();
        fun2();
    }
   else
   {
     switch(i)
     {
       
     case 1:
       printf("In fun1 /n");
     break;
   case 2:
     printf("In fun2/n");
     break;
   default:
     printf("unkown error/n");
     break;
     }
          exit(0);
   }
    return 1;
}

void fun1(void)
{
    char *s = "hello";
    char *s1 = "Hello";
    if(strcmp(s,s1)!=0)
    longjmp(jmpbuffer,1);
}

void fun2(void)
{
    char *s = "world";
    if(strcmp(s,"World")!=0)
    longjmp(jmpbuffer,2);
}

这个函数的运行结果是:


[email protected]:~/program/test_program$ ./jmp_test
first run
In fun1

在使用longjmp跳转到setjmp中时,程序主动的退出了!相当于抛出一个异常退出!其实这两个函数可以模拟C++中的异常函数:(vanishfan注:可以类比着理解)
使用setjmp和longjmp要注意以下几点:
  1、setjmp与longjmp结合使用时,它们必须有严格的先后执行顺序,也即先调用setjmp函数,之后再调用longjmp函数,以恢复到先前被保存的“程序执行点”。否则,如果在setjmp调用之前,执行longjmp函数,将导致程序的执行流变的不可预测,很容易导致程序崩溃而退出
 2、不要假设寄存器类型的变量将总会保持不变。在调用longjmp之后,通过setjmp所返回的控制流中,程序中寄存器类型的变量将不会被恢复。寄存器类型的变量,是指为了提高程序的运行效率,变量不被保存在内存中,而是直接被保存在寄存器中。寄存器类型的变量一般都是临时变量,在C语言中,通过register定义,或直接嵌入汇编代码的程序。这种类型的变量。
     longjmp必须在setjmp调用之后,而且longjmp必须在setjmp的作用域之内。(vanishfan注:这两点很重要!)具体来说,在一个函数中使用setjmp来初始化一个全局标号,然后只要该函数未曾返回,那么在其它任何地方都可以通过longjmp调用来跳转到 setjmp的下一条语句执行。实际上setjmp函数将发生调用处的局部环境保存在了一个jmp_buf的结构当中,只要主调函数中对应的内存未曾释放 (函数返回时局部内存就失效了),那么在调用longjmp的时候就可以根据已保存的jmp_buf参数恢复到setjmp的地方执行。

vanishfan注:

【原创】setjmp longjump一些注意点及使用方法

时间: 2024-08-30 01:37:08

【转载】setjmp和longjmp函数使用详解的相关文章

PHP date函数参数详解

PHP date函数参数详解 作者: 字体:[增加 减小] 类型:转载 time()在PHP中是得到一个数字,这个数字表示从1970-01-01到现在共走了多少秒,很奇怪吧 不过这样方便计算, 要找出前一天的时间就是 time()-60*60*24; 要找出前一年的时间就是 time()*60*60*24*365 那么如何把这个数字换成日期格式呢,就要用到date函数了 $t=time();  echo date("Y-m-d H:i:s",$t); 第一个参数的格式分别表示: a -

PHP函数篇详解十进制、二进制、八进制和十六进制转换函数说明

PHP函数篇详解十进制.二进制.八进制和十六进制转换函数说明 作者: 字体:[增加 减小] 类型:转载 中文字符编码研究系列第一期,PHP函数篇详解十进制.二进制.八进制和十六进制互相转换函数说明,主要掌握各进制转换的方法,以应用于实际开发 一,十进制(decimal system)转换函数说明 1,十进制转二进制 decbin() 函数,如下实例 echo decbin(12); //输出 1100 echo decbin(26); //输出 11010 decbin (PHP 3, PHP

CGBitmapContextCreate函数参数详解

CGBitmapContextCreate函数参数详解 函数原型: CGContextRef CGBitmapContextCreate ( void *data,   size_t width,   size_t height,   size_t bitsPerComponent,   size_t bytesPerRow,   CGColorSpaceRef colorspace,   CGBitmapInfo bitmapInfo ); 参数: data                  

PE文件结构与函数导出表——详解与实例

PE文件结构与函数导出表--详解与实例 随着windows系统从Xp升级到Win7.Win8, 从32位升级到64位,PE文件结构在整体未变的情况下发生了一些小的变动,一方面是推荐的程序装载地址未采用,另一方面,导出函数序号不再是简单的升序,而是一定程度上的进行了乱序.本文首先对PE文件结构进行了详尽的解说,接着介绍了如何得出函数导出表,整个过程采用SysWoW64目录下的wininet.dll实例进行说明.在介绍过程中,明确指出了Win7.Win8等新系统相对Xp带来的区别. 文章链接:htt

Python学习入门教程,字符串函数扩充详解

因有用户反映,在基础文章对字符串函数的讲解太过少,故写一篇文章详细讲解一下常用字符串函数.本文章是对:程序员带你十天快速入门Python,玩转电脑软件开发(三)中字符串函数的详解与扩充. 如果您想学习并参与本教程的完善与写作.请在下方讨论区,回复相关问题.一起完善本文章教程的书写. Python字符串常用函数. 声明字符串变量: str = ‘关注做全栈攻城狮,写代码也要读书,爱全栈,更爱生活.’ 下面所有字符串函数函数,是对变量str进行操作: 求字符串长度: 函数使用: 运行结果: 值得注意

自写函数VB6 STUFF函数 和 VB.net 2010 STUFF函数 详解

'*************************************************************************'**模 块 名:自写函数VB6 STUFF函数 和 VB.net 2010 STUFF函数 详解'**说    明:蓝凤凰设计商城 浴火凤凰-郭卫 | 蓝凤凰-魔灵 | 郭卫-icecept'**创 建 人:浴火凤凰-郭卫'**日    期:2015年10月10日  23:13:55'**修 改 人:浴火凤凰-郭卫'**日    期:'**描   

学习之&quot;setjmp和longjmp函数&quot;

Linux学习之"setjmp和longjmp函数" 转贴,原文地址:http://www.cnblogs.com/lq0729/archive/2011/10/23/2222117.html nsetjmp和longjmp函数实现函数之间的跳转(需包含头文件"setjmp.h"): 函数原型:int setjmp(jmp_buf env);   void longjmp(jmp_buf env, int val); setjmp函数用于设置跳转的目的位置,long

ThinkPHP源码阅读2-----C函数配置文件详解

ThinkPHP的配置非常灵活,可自定义加载.大概看了一下,一共有这几个地方会加载配置文件,方便以后的读取 /** * 获取和设置配置参数 支持批量定义 * * @param string|array $name * 配置变量 * @param mixed $value * 配置值 * @return mixed */ function C($name = null, $value = null) { static $_config = array (); // 无参数时获取所有 if (emp

wp_list_categories函数用法详解

本以为写完新手教程之后,可以不写新手应用方面的文章了的,可今天又有朋友在群里问如何显示每个分类下文章数量这个基础性问题,看来Wordpress中文化还有很长的一段路要走,我们任重而道远啊!好,解决你的问题先:正如标题所说,Wordpress是用wp_list_categories这个函数来显示分类的,其用法是:< ?php wp_list_categories('arguments'); ?>arguments即参数,默认参数设置为: $defaults = array('show_optio