setjmp与logjmp用法总结

setjmp/logjmp的最大用途是错误恢复,只要还没有从主函数退出,一旦发现一个不可恢复的错误,可以把主控制转移大主函数循环,并从那从新开始。使用时必须包含头文件<setjmp.h>

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


  setjmplogjmp的使用场合:

1.人们对于goto语句的忌讳,很多的专业书籍以及专业人士号召限制goto语句的使用,此时,setjmplongjmpgoto语句有了很好的替代作用.
2.goto
语句有一个局限性,它只能在函数内部跳转.setjmplongjmp可以在整个程序全局中跳转,实现"长跳转",弥补了goto功能的局限
.
3.
使用setjmplongjmp可以捕捉程序中的异常,并采取异常处理机制.



一个例子  使用setjmp,longjmp处理异常.


  1 #include<stdio.h>
  2 #include<setjmp.h>
  3 jmp_buf jumper;
  4 void exception();
  5 int deal_exception();
  6
  7 main()
  8 {
  9         int value;
 10         int i=0;
 11
 12         value=setjmp(jumper);
 13         if(0==value){
 14                 exception();
 15         }
 16         else{
 17                 switch(value)
 18                 {
 19                         case 1:
 20                                 printf("解决异常情况[%d]\n",value);
 21                                 break;
 22                         case 2:
 23                                  printf("解决异常情况[%d]\n",value);
 24                                  break;
 25                         case 3:
 26                                  printf("解决异常情况[%d]\n",value);
 27                                  break;
 28
 29                         default:
 30
 31                                  break;
 32                 }
 33         }
 34 }
 35 void exception()
 36 {
 37         int _err_no;
 38         if(_err_no=3){
 39                 printf("出现异常情况[%d]\n",_err_no);
 40                 longjmp(jumper,_err_no);
 41         }
 42         return;
 43 }

结果:
[root@localhost test]# gcc error.c
[root@localhost test]# ./a.out
出现异常情况[3]
解决异常情况[3]
[root@localhost test]#

C语言的try and catch机制

C语言具有的类似try and catch机制,unix下机制也相同。

VC例子:

#include <stdio.h>

#include <setjmp.h>

jmp_buf mark;  // 保存stack环境的变量

 

void main(void)

{

int jmpret;

int result;

jmpret = setjmp( mark );  @1@ // 保存当前stack环境到mark变量

if( jmpret == 0 )

{

scanf("%d",&result);

if(result<0) {

longjmp( mark, -1 );  // 发生错误,恢复保存的stack环境,执行跳转到@1@处,jmpret的值为-1

return;

     // 此语句永远不被执行

} else {

printf("Normal!");

return;

}

} else {

// 错误处理

printf("An exception occured!");

}

}

 

 

longjmp在Standard C中的说明:

1.用longjmp跳转时保证静态变量有正确的值

2.auto变量只保证拥有volatile类型和在setjmp和longjmp之间没有改变的值。

解释:

1.静态变量保持为在longjmp调用时的值

2.在setjmp和longjmp之间没有改变的值仍然是原值,(很简单,因为从来就没有改变过)

对于一些auto-nonvolatile的值,可能在循环中,编译器为了优化性能,用寄存器来缓存,longjmp跳转时没有赋值,用volatile修饰能阻止编译器优化。

这两个函数都要包含头文件setjmp.h。而且它们在处理出现在深层函数嵌套的错误情况时很有用处。
    setjmp这个函数很有意思,虽然是一个函数,可是却可以返回两个不同的值。当第一次直接调用setjmp时,返回值为0。当从longjmp函数返回时,setjmp函数的返回值为longjmp的第二个参数的值。
    那么在什么地方调用setjmp呢?我们希望当从longjmp函数返回时,程序从哪里接着开始运行,我们就在哪里调用setjmp。看个小实例,你就明白是怎么回事了。

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

    jmp_buf ebuf;
    void f2(void);
   int main(void)
   {
     int i;
     printf("1");
     i=setjmp(ebuf);
     if(i==0)                                              //第一次执行到这里时,值为0,所以接下来执行f2()
     {
   f2();
   printf("This will not be printed.");
     }
     printf("%d",i);                                    //由于从longjmp返回时,i=3,不执行if,所以执行该行
     return 0;
}
   void f2(void)
{
   printf("2");                                         
   longjmp(ebuf,3);                     //longjmp函数返回,回到setjmp的位置,使得setjmp返回值为3
}
    函数最后的执行结果为123,嘻嘻。

      longjmp注意:
  1.不要假象寄存器类型的变量将总会保持不变。在调用longjmp之后,通过setjmp所返回的控制流中,例程中寄存器类型的变量将不会被恢复。
  2.不要使用longjmp函数来实现把控制流,从一个中断处理例程中传出,除非被捕获的异常是一个浮点数异常。在后一种情况下,如果程序通过调用 _fpreset函数,来首先初始化浮点数包后,它是可以通过longjmp来实现从中断处理例程中返回。
  3. 在C++程序中,小心对setjmp和longjmp的使用,应为setjmp和longjmp并不能很好地支持C++中面向对象的语义。因此在C++程序中,使用C++提供的异常处理机制将会更加安全。把setjmp和longjmp组合起来,原来它这么厉害

使用setjmp时必须使用头文件setjmp.h。

#include "setjmp.h"

jmp_buf jmpbuffer;
 
int setjmp(jmp_buf jmpbuffer);
void longjmp(jmp_buf jumpbuffer, int retval);
 
其中 jmpbuffer 是相关的程序栈的环境上下文。
初始化jmpbuffer之后, setjmp第一次调用的时候会返回 0。
longjmp跳转到setjmp处,其中第二个参数retval就是传递给setjmp, 作为setjmp的返回值。但是需要主要的是,如果retval设置为0, 即这样调用的时候 longjmp(jumpbuffer, 0), setjmp会返回1。

函数setjmp()的行为很特别,如果直接调用它,它便将所有与当前处理器相关的状态信息(比如指令指针的内容,栈指针等)保存到jmp_buf中并返回0。在这种情况下,它的表现与一个普通的函数一样。然而,如果使用同一个jmp_buf调用longjmp(),则函数返回时就好像刚从setjmp()中返回时一样-----又回到刚刚从setjmp()返回的地方。这一次,返回值是调用longjmp()时所使用的第二个参数,因此可通过这个值判断程序是从longjmp()返回的

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.mzph.cn/news/254047.shtml

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈email:809451989@qq.com,一经查实,立即删除!

相关文章

JQ对象到底是什么

jQuery对象是什么&#xff0c;举个例子&#xff0c;$(#id) 返回的就是jQuery对象&#xff0c;这个东西是整个jQuery的核心所在&#xff0c;所以我先来分析它。 var jQuery function( selector, context ) { // The jQuery object is actually just the init constructor enhan…

15、iOS开发之duplicate symbols for architecture x86_64错误

1. 错误提示 2. 分析错误原因 3. 解决问题办法 一、错误提示 在我们写代码过程中可能会经常遇到这样一个错误&#xff1a; [objc] view plaincopy print?<span style"font-size:32px;color:#ff0000;">ld: 4 duplicate symbols for architecture x86_64 clang…

【死磕Java并发】----- 死磕 Java 并发精品合集

【死磕 Java 并发】系列是 LZ 在 2017 年写的第一个死磕系列&#xff0c;一直没有做一个合集&#xff0c;这篇博客则是将整个系列做一个概览。 先来一个总览图&#xff1a; 【高清图&#xff0c;请关注“Java技术驿站”公众号&#xff0c;回复&#xff1a;脑图JUC】 【死磕Java…

vs官方使用教程中文版与英文版

Visual Studio IDE 中文文档 https://docs.microsoft.com/zh-cn/visualstudio/ide/ Visual Studio IDE documentation https://docs.microsoft.com/en-us/visualstudio/ide/

linux subsys_initcall

宏定义__define_initcall(level,fn)对于内核的初始化很重要&#xff0c;他指示编译器在编译的时候&#xff0c;将一系列初始化函数的起始地址值按照一定的顺序放在一个section中。在内核初始化段&#xff0c;do_initcalls() 将按顺序从该section中以函数指针的形式取出这些函数…

vue transition

Vue.js 教程 (9) : 过渡动画 Vue.js 提供非常简单的过渡动画接口。这些过渡动画在 Vue.js 将目标元素插入或移除出 DOM 的时候会自动执行。能够触发动画的指令包括 v-if , v-show 和 v-repeat。同时&#xff0c;vm 实例的 $appendTo() , $before() , $after() 和 $remove() 方法…

VS扩展工具

原文发布时间为&#xff1a;2011-03-09 —— 来源于本人的百度文章 [由搬家工具导入]http://visualstudiogallery.msdn.microsoft.com/site/search?f%5B0%5D.TypeRootCategory&f%5B0%5D.Valuetools转载于:https://www.cnblogs.com/handboy/p/7163982.html

工业相机5A参数及其对图像采集的影响

有些相机会提到5A功能&#xff0c;指的是: Automatic Shutter(自动快门)、Automatic Gain&#xff08;自动增益&#xff09;、Automatic IRIS&#xff08;自动光圈&#xff09;、Automatic Gamma&#xff08;自动伽马&#xff09;、Automatic White Balance&#xff08;自动白平…

DM6446 OSD

DM6446 OSD TMS320DM6446支持背景窗颜色&#xff0c;两个视频窗口&#xff0c;两个OSD窗口&#xff0c;一个指针(cursor)窗口。它们以递增的顺序排列&#xff1a;一个特有的第二个OSD窗口&#xff08;OSDWIN1&#xff09;可以用来配置成属性窗口来控制视频窗口和第一个OSD窗口&…

DOS的一些常用命令

原文发布时间为&#xff1a;2011-02-12 —— 来源于本人的百度文章 [由搬家工具导入]DOS远程桌面连接命令 mstsc /v: 192.168.1.250 /consolecmd 运行 command删除文件 rd 文件名/S创建文件 MD 文件名 1. net user admin godmour /add 新建一个…

机器视觉工业镜头-Computar

日本Computar镜头&#xff0c;全球工业镜头、CCTV镜头市场占有率第一。CBC板式会社成立于1925年&#xff0c;总部在日本东京。1960年 CBC香港公司成立&#xff0c;是computar镜头走向国际市场的前奏。 1979年 研制出第一只手动变焦镜头。 1985年 研制出第一款非球面高速镜头。1…

C++编程经验总结1

面向对象的精髓&#xff1a; 主函数其实就是对于类的元素和动作的重新组合来进行一项活动。 一个思想概念&#xff1a;程设是清楚的&#xff0c;完美的。 数学是清楚的&#xff0c;是完美的。 物理是有趣的&#xff0c;尤其是量子物理 生物是清楚的&#xff0c;尤其是基因 外语…

DM365的BSP源码分析-基于2.6.18内核

DM365的BSP主要包含mach-davinci和plat-davinci两个目录&#xff08;及相关头文件&#xff09;&#xff0c;BSP复杂庞大又极其重要&#xff0c;它主要完成了板级的初始化&#xff0c;比如内存映射&#xff0c;时钟和电源初始化&#xff0c;中断和IO初始化&#xff0c;CPU及各模…

第四章:Django 模型 —— 设计系统表

1. Django框架提供了完善的模型&#xff08;Model &#xff09;层来创建和存储数据&#xff0c;每一个模型对应数据库中的唯一的一张表。 2. Django 模型基础知识&#xff1a; 。每一本模型是一个Python类&#xff0c;继承了django.db.models.Model类 。该模型中每一个属性一个…

DM365 使用BT656协议驱动LCD的实现

前两天已经调好了&#xff0c;主要是对davinci_platform.c的修改 因为输入输出都为pal的制式&#xff0c;所以就在pal的函数中进行了修改。 在PAL设置的函数中&#xff0c;修改如下&#xff1a; /* * setting PAL mode */ static void davinci_enc_set_pal(struct vid_enc_mode…

工业视觉镜头NAVITAR

品牌介绍 美国NAVITAR是优越的上等光学系统制造商和供应商&#xff0c;工业视觉镜头NAVITAR为机器视觉、检测和生物医学诊断行业提供的定制光学解决方案。 工业视觉镜头NAVITAR用于鉴定产品、检查产品缺陷、测量零件尺寸、操纵机器人设备和协助进行科学分析与探索。 还用来引导…

TCP系列48—拥塞控制—11、FRTO拥塞撤销

一、概述FRTO虚假超时重传检测我们之前重传章节的文章已经介绍过了&#xff0c;这里不再重复介绍&#xff0c;针对后面的示例在说明两点1、FRTO只能用于虚假超时重传的探测&#xff0c;不能用于虚假快速重传的探测。2、延迟ER重传触发的进入Recovery状态时候&#xff0c;并不会…

娱乐一下

6年前&#xff0c;没几个人知道尤里米尔纳&#xff08;Yuri Milner&#xff09;是谁。但今天&#xff0c;他已经是地球上最有名的投资人了。 短短几年内&#xff0c;这家伙掌管的风险投资基金DST&#xff08;数字天空科技&#xff09;投遍了全球的互联网明星企业&#xff0c;并…

机器视觉行业市场现状及发展前景分析

1.中国的机器视觉起步较晚&#xff0c;目前正处于快速增长期。 我国机器视觉最早起源于20世纪80年代。机器视觉生产线和先进设备自1998年众多电子、半导体企业落户广东、上海以来&#xff0c;先后在国内诞生了国际代理商和机器视觉系统集成商。 第一个阶段是1999-2003年的启蒙…