`
wenzongliang
  • 浏览: 448770 次
  • 性别: Icon_minigender_1
  • 来自: 北京
文章分类
社区版块
存档分类
最新评论

c模拟try catch

 
阅读更多

非局部跳转语句---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);
}

这个函数的运行结果是:

root@root:~/program/test_program$ ./jmp_test
first run
In fun1

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

 

实例:https://github.com/FredericGuo/CoffeeCatch.JNI

分享到:
评论

相关推荐

    C语言模拟实现 try catch

    在C语言中,使用goto和标签的方式模拟try catch的功能,使用setjmp和longjmp方式模拟try catch的功能,两种方式都可以使用,setjmp的方式可以支持try catch嵌套,goto的方式不支持嵌套,但是jmpbuf的开销是比较大的...

    Jsoup+httpclient 模拟登陆和抓取

    } catch (IOException e) { e.printStackTrace(); } return url; } public static void main(String[] args) throws Exception { String [] params={"admin","admin123"}; HttpClient client = ...

    SpringBoot专题学习Part29:SpringBoot的Async异步任务、Scheduled定时任务、mail邮件发送任务

    一、Async异步任务 ...首先来模拟一个同步任务响应迟缓的场景 以供比较: Service: @Service public class AsyncService { public void hello() { try { Thread.sleep(2000); } catch (Interr

    简单谈谈javascript高级特性

    js中没有class的概念,我们可以使用function来模拟。 惰性载入函数 例如我们通常使用以下的js代码创建ajax: function createXHR () { var xhr = null; try{ xhr = new XMLHttpRequest(); // FF、Opera、Safari...

    编辑器源码下载,电信项目中用到过

    body.html 『模拟多行文本域的页』 &lt;!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN" "http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd"&gt; ; charset=gb2312" /&gt; 无标题文档 &lt;!-- ...

    HttpClient以及获取页面内容应用

    } catch (UnsupportedEncodingException e1) { e1.printStackTrace(); } catch (IOException e) { e.printStackTrace(); } finally { // 关闭连接,释放资源 try { httpclient.close(); } ...

    C++大学教程,一本适合初学者的入门教材(part2)

    13.4 C十十异常处理基础:try、throw、catch 13.5 简单异常处理例子:除数为o 13.6 抛出异常 13.7 捕获异常 13.8 再抛出异常 13.9 异常指定 13.10 处理意外异常 13.11 堆栈解退 13.12 构造函数、析构函数与...

    新手学习C++入门资料

    C++中的try/catch/throw异常处理机制取代了标准C中的setjmp()和longjmp()函数。 二、关键字和变量 C++相对与C增加了一些关键字,如下: typename bool dynamic_cast mutable namespace static_cast using ...

    JAVA 范例大全 光盘 资源

    实例73 运用throws、throw、try与catch 183 实例74 throws声明异常的实例 185 实例75 自定义异常类 187 实例76 使用finally避免资源漏洞 189 实例77 反射机制 191 第10章 I/O及文件操作 196 实例78 创建文件和...

    异步mysql客户端async-mysql-php.zip

    在实际的开发过程中,我们常常会遇到需要操作多张表,多个库的情况。有时因为一些限制我们不能进行连表(例如,异地数据库),所以只能用php串行访问后再在...conf: 'prod_33c27aefa42004c9b2c12a759c851039' });

    C++大学教程,一本适合初学者的入门教材(part1)

    13.4 C十十异常处理基础:try、throw、catch 13.5 简单异常处理例子:除数为o 13.6 抛出异常 13.7 捕获异常 13.8 再抛出异常 13.9 异常指定 13.10 处理意外异常 13.11 堆栈解退 13.12 构造函数、析构函数与...

    Java 语言基础 —— 非常符合中国人习惯的Java基础教程手册

    观事务的软件化模拟,是变量(数据和数据结构)和相关方法(对数据操作和对象管理的程 序)的软件组合。 在面向对象的程序设计中,你可以用软件对象表示现实世界的对象,而这些软件对象和 现实世界对象是相对应的。...

    JavaScript完全自学宝典 源代码

    4.5.html try-catch-finally语句执行流程。 第5章(\c05) 示例描述:介绍JavaScript文档对象模型。 5.1.html 使用DOM获取各级别节点。 5.2.html 使用DOM获取body元素。 5.3.html 获取元素的子节点...

    微信客服管理 集成微信接口、聊天机器人 免费注册使用

    2、本系统所有操作都是通过模拟控制网页实现,请不要直接操作右边的“微信网页版”,以免影响本软件的正常操作。 3、建议一个注册账号只对应一个微信账号,否则历史信息会混乱。 4、本软件免费用户信息带尾巴...

    C++大学教程

    1.7 C语言与C++的历史--------------------------------------------------6 1.8 C++标准库---------------------------------------------------------7 1.9 Java、Internet与万维网-------------------------...

Global site tag (gtag.js) - Google Analytics