非本地跳转(unlocal jump)是与本地跳转相对应的一个概念。

本地跳转主要指的是类似于goto语句的一系列应用,当设置了标志之后,可以跳到所在函数内部的标号上。然而,本地跳转不能将控制权转移到所在程序的任意地点,不能跨越函数,因此也就有了非本地跳转

C语言里面提供了setjmplongjmp函数来进行跨越函数之间的控制权的跳转,从而称之为非本地跳转。

#include <setjmp.h>
int setjmp(jmp_buf env);

该函数主要用来保存当前执行状态,作为后续跳转的目标。调用时,当前状态会被存放在env指向的结构中,env将被 long_jmp 操作作为参数,以返回调用点,跳转的结果看起来就好像刚从setjmp返回一样。

需要注意的是,第一次调用setjmp的时候返回值为0;而从long_jmp操作返回时,返回值是非0的,数值与longjmp传入的参数value有关。通过判断setjmp的返回值,就可以判断当前执行状态。

#include<setjmp.h>
void long_jmp(jmp_buf env, int value);

该函数用来恢复env中保存的执行状态,另一参数value用来传递返回值给跳转目标。如果value值为0,则跳转后返回setjmp处的值为1;否则,返回setjmp处的值为value

因此,整个非本地跳转的执行过程是:首先,在程序中调用setjmp进行当前运行栈环境的保存,接着在程序的其它地方调用longjmp进行跳转,跳转回的位置就是该setjmp的位置。

这其中需要注意的是:jmp_buf类型的变量env,因为该变量保存的是当前执行位置的运行栈环境;因此如果需要还能跳转到这个位置,那么longjmp必须能调用到这个env变量,因此这个变量一般为全局的。

接下来,简单的介绍一下运行栈的概念。

运行栈

简单的来说,程序运行的时候如果一个函数Fa内部调用了另一个函数Fb,那么当Fb执行完了之后,控制权如何返回给Fa,并继续执行Fa后面的语句呢?这就使用到了运行栈。

简要的说,运行栈里按照函数调用的顺序将一个个函数压入栈中,当一个函数执行结束之后,这个函数的栈帧(stack frame)就会从运行栈中pop出来,并将控制权(PC)转向调用函数(callee),控制权的记录就在每个函数所对应的的栈帧中。

因此,如果我们有程序段如下:

void Fa()
{
...
Fb();
...
}
void Fb()
{
...
Fc();
...
}
void Fc()
{
...
//do something here
} void main()
{
...
Fa();
}

那么,当调用到函数Fc时程序的运行栈大致如下图所示:

当执行完Fc之后就会将Fc的栈帧pop出来,如下图所示:

非本地跳转模拟异常处理机制

当使用非本地跳转时,就不需要一层层的解开程序调用栈,而是直接将控制流转移到对应的位置。

在最初,还没有实现异常处理机制的时候,有的时候会用非本地跳转来模拟异常处理机制,大致思路如下:

#define myTry if(setjmp(env) == 0){

#define myCatch(err) }else if(err != NULL){ \
//TO DO SOMETHING HERE
\
} #define myThrow(err) longjmp(env, err.ToInteger())

在myTry处设置setjmp,并保存当前的程序运行栈到env中,当程序中某个函数throw出一个异常时,就使用longjmp进行跳转。此时,程序又回到了setjmp处,但是因为返回值已经被设置为err.ToInteger(),因此setjmp的返回值肯定不是0,于是程序就进入到了else if分支,即myCatch语句块中。

但是,使用非本地跳转来模拟异常处理机制时会产生一定的问题,那就是在语句块中定义的局部变量所占的内存并不会被正常的释放,导致内存泄漏。

因为,非本地跳转在发生跳转时是直接将程序的控制流转移过去,而不是进行正常的栈退解(stack unwinding)操作,因此并不能识别出其中的变量并进行析构,不过现在的一些编译器已经实现了相应的功能,因编译器而异。

非本地跳转之setjmp与longjmp的更多相关文章

  1. 【转】浅析C语言的非局部跳转:setjmp和longjmp

    转自 http://www.cnblogs.com/lienhua34/archive/2012/04/22/2464859.html C语言中有一个goto语句,其可以结合标号实现函数内部的任意跳转 ...

  2. Unix系统编程()执行非局部跳转:setjmp和longjmp

    使用库函数setjmp和longjmp可执行非局部跳转(local goto). 术语"非局部(nonlocal)"是指跳转目标为当前执行函数之外的某个位置. C语言里面有个&qu ...

  3. (C)非局部跳转语句(setjmp和longjmp)

    1. 特点 非goto语句在函数内实施跳转,而是在栈上跳过若干调用帧,返回到当前函数调用路径上的某一语句. 头文件包含#include Void longjmp(jmp_buf env,int val ...

  4. C语言中setjmp与longjmp学习笔记

    C语言中setjmp与longjmp学习笔记 一.基础介绍 头文件:#include<setjmp.h> 原型:  int setjmp(jmp_buf envbuf) ,然而longjm ...

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

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

  6. setjmp和longjmp函数使用详解

    源地址:http://blog.csdn.net/zhuanshenweiliu/article/details/41961975 非局部跳转语句---setjmp和longjmp函数.非局部指的是, ...

  7. setjmp与longjmp非局部跳转函数的使用

    [root@bogon code]# cat c.c #include<stdio.h> #include<setjmp.h> static jmp_buf env;//定义全 ...

  8. C和指针 第十六章 标准函数库 本地跳转setjmp.h

    setjmp和longjmp提供一种类似goto语句的机制,但它的作用域不局限于同一个函数的作用域之内.这些函数可以用于深层次的嵌套函数调用链. int setjmp(jmp_buf state); ...

  9. setjmp()、longjmp() Linux Exception Handling/Error Handling、no-local goto

    目录 . 应用场景 . Use Case Code Analysis . 和setjmp.longjmp有关的glibc and eglibc 2.5, 2.7, 2.13 - Buffer Over ...

随机推荐

  1. throw exception

    Throw new CustomerException('Customer message'); // App\Exceptions\Handler.php public function rende ...

  2. sql笔记-group by 统计功能

    --查询月销售量小于20的人员销售情况 SELECT C.Category, SUM(c.[Count]) AS CategorySum FROM test.dbo.Category c --WHER ...

  3. Source Insight 3.X 插件新loader发布

    [前言] 大约一年多没更新SI插件了,主要原因是我从SI换到了sublime,使用SI少了,插件也就停止更新了.不过看到园子里这么多网友的留言,觉得还是有必要更新一下,算是给还在用SI的朋友们一个交代 ...

  4. PS通过滤色实现简单的图片拼合

     素材如下: 素材一: 雪山 素材二: 月亮  效果: 实现步骤 1.在PS中打开雪山素材一 2.将月亮素材直接拖入雪山所在的图层中 3.锁定置入素材的高宽比(点击一下链状按钮) 4.调整月亮到合适大 ...

  5. RDIFramework.NET-.NET快速信息化系统开发整合框架 【开发实例 EasyUI】之产品管理(MVC版)

    RDIFramework.NET—.NET快速开发整合框架 [开发实例]之产品管理(MVC版) 接上篇:RDIFramework.NET (.NET快速信息化系统开发整合框架) [开发实例]之产品管理 ...

  6. [Android Tips] 22. Available Java 7 Features in Android

    This only allows Java 7 language features, and you can hardly benefit from anything since a half of ...

  7. sql 中convert和cast区别

    SQL中的cast和convert的用法和区别 更多 来源:SQL学习浏览量: 学习标签: cast convert sql 本文导读:SQL中的cast 和convert都是用来将一种数据类型的表达 ...

  8. 罗永浩专访全文记录(转自好奇心日报-http://www.qdaily.com/)

    这篇文章是转的,存档做记录,定期看一看,激励自己遇到到困难时,想想人家比自己难多了,自己那点事算个屁啊.学习别人,不要带有傻逼主观倾向性,这样什么也得不到,我看完后,发现有一句话,说的非常好,自己有自 ...

  9. ios-深度解析二维码的生成与使用

    利用一个小demo来对二维码进行学习,总共四个界面(主界面,生成二维码界面,识别二维码界面,扫描二维码界面)   一.二维码的介绍   1.什么是二维码?        二维条码/二维码是用某种特定的 ...

  10. IOS在线安装App

    在越狱设备上可以安装,如果设备不越狱也想安装,就要企业发布权限了,可惜我没有,所以不能测试了! 1.创建ipa及plist文件: XCode菜单栏->Product->Archive-&g ...