C中的setjmp与longjmp
setjmp与longjmp是属于C语言中的,当然,C++也会有这两个函数了。他们的原型如下:
作用:第一次调佣时,将寄存器的当前状态信息全部存入到env中,并返回0。如果在某处调用了longjmp(env,x),且x!=0,则setjmp的返回值将设为x。而若x==0,则setjmp返回1。
作用:重新存储当前寄存器的状态信息,并将setjmp的返回值设为value。
简单概括之,如果你有月光宝盒,那么需要将月光宝盒在某处定一个时间点,比如2015年11月11日11点11分,后来,我在2016年感觉不爽,就直接使用月光宝盒回到2015年11月11日11点11分,当时所有的东西仍然没有变化,仅仅只有我知道我穿越了。那么setjmp就是用于设置时间点,会将必须的东西记录下来,保存在一个jmp_buf类型的变量中,此后,如果有longjmp想回到这个时间点,就可以直接跳回去。值得注意的是,这样不就一直在无限循环吗?当然还是有变化的,第一次调用setjmp时,返回的是0。当调用longjmp跳回去时,setjmp的返回值变成了非0值,这样就可以区分开来了。
下面是个例子:
void test()
{
jmp_buf jb;
int ret=setjmp(jb); //设置返回点,返回0.
if(ret!=) cout<<""<<endl; //这仅被输出1次。
if(ret==) longjmp(jb,);//回到jb处,并将ret设为非零。
}
那么setjmp与longjmp在C++中的适用范围是什么?setjmp与longjmp如果跳出了当前函数的话,当前函数中声明的对象可是不会被析构的(不会调用析构函数),那么就存在了一定的危险,比如对象里还有动态申请的内存怎么办,然而C中就不存在这个问题了。并不是说不能用,只是必须了解它的利弊,才能更好地使用他。
例子:
class Rainbow
{
public:
Rainbow() {cout<<"Rainbow()"<<endl;}
~Rainbow() {cout<<"~Rainbow()"<<endl;}
};
jmp_buf jmpBuf;
void Summer()
{
Rainbow rb;
for(int i=;i>;--i)
cout<<"Happy Chinese Valentine's Day!"<<endl;
longjmp(jmpBuf,); //下面这句被忽略
cout<<"Oh no.I am being ignore."<<endl;
} int main()
{
test();
if(!setjmp(jmpBuf))
{
cout<<"setjmp() return a zero value!"<<endl;
Summer();
}
else
{
cout<<"setjmp() get a non-zero value!"<<endl;
}
return ;
}
经测试,G++下并不会调用该析构函数。当然,你需要考虑编译器的智能程度,可能帮你做优化了。
这种方法看起来与goto相似,但是是有区别的,区别如下:
(1)goto语句不能跳出C语言当前的函数。
(2)用longjmp只能跳回曾经到过的地方。在执行setjmp的地方仍留有一个过程活动记录。从这个角度上讲,longjmp更象是“从何处来”,而不是“要往哪去”。另外,longjmp接受一个额外的整形参数并返回它的值,这可以知道是由longjmp转移到这里的还是从上一条语句执行后自然执行到这里的。
参考:http://blog.csdn.net/cscmaker/article/details/7584433
C中的setjmp与longjmp的更多相关文章
- setjmp()和longjmp()函数
之前我们讲到了过程活动记录(AR),那么如何来操纵AR呢,一个可能的方法是,根据局部变量的地址进行推算,例如对于上面的a函数,执行a函数时的当前AR地址就是参数i的地址偏移8个字节,也就是 ((cha ...
- C 语言中 setjmp 和 longjmp
在 C 语言中,我们不能使用 goto 语句来跳转到另一个函数中的某个 label 处:但提供了两个函数——setjmp 和 longjmp来完成这种类型的分支跳转.后面我们会看到这两个函数在处理异常 ...
- 非本地跳转之setjmp与longjmp
非本地跳转(unlocal jump)是与本地跳转相对应的一个概念. 本地跳转主要指的是类似于goto语句的一系列应用,当设置了标志之后,可以跳到所在函数内部的标号上.然而,本地跳转不能将控制权转移到 ...
- 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 ...
- setjmp 与 longjmp
setjmp和longjmp是C语言独有的,只有将它们结合起来使用,才能达到程序控制流有效转移的目的,按照程序员的预先设计的意图,去实现对程序中可能出现的异常进行集中处理. 先来看一下这两个函数的定义 ...
- setjmp和longjmp的使用
问题描述: setjmp和longjmp的使用 问题解决: setjmp和longjmp是C语言独有的,只有将它们结合起来使用,才能达到程序控制流有效转移的目的,按照程序 ...
- 【转】浅析C语言的非局部跳转:setjmp和longjmp
转自 http://www.cnblogs.com/lienhua34/archive/2012/04/22/2464859.html C语言中有一个goto语句,其可以结合标号实现函数内部的任意跳转 ...
- 【转载】setjmp和longjmp函数使用详解
[说明]本文上半部分转载自 wykwdy007 的转载文章 http://blog.csdn.net/wykwdy007/article/details/6535322 --------------- ...
- 进程环境之setjmp和longjmp函数
在C中,goto语句是不能跨越函数的,而执行这样跳转功能的是函数setjmp和longjmp.这两个函数对于处理发生在深层嵌套函数调用中的出错情况是非常有用的. setjmp和longjmp函数也称为 ...
随机推荐
- ajax简单封装
var xmlhttp = window.XMLHttpRequest ? new XMLHttpRequest() : new ActiveXObject('Microsoft.XMLHTTP'); ...
- Linux下配置用msmtp和mutt发邮件
Linux下可以直接用mail命令发送邮件,但是发件人是user@servername,如果机器没有外网的dns,其他人就无法回复.此时,有一个可以使用网络免费邮箱服务的邮件发送程序就比较重要了.ms ...
- myeclipse中java文件中文注释乱码问题
在myeclipse中,有时打开java文件会发现中文注释全为乱码了,这个问题主要是因为编码的问题没有设置好,一个重要的原则就是保证所有的编码一致才不会发生乱码 出现乱码,需要知道三个地方的编码格式: ...
- linux 执行php文件
/opt/php5/bin/php /home/Xcar/tag/interface/tag_api4hbase.php tag_export2file "/tmp/guo.php" ...
- Linux-编译器gcc/g++编译步骤
gcc和g++现在是gnu中最主要和最流行的c&c++编译器.g++是c++的命令,以.cpp为主:对于c语言后缀名一般为.c,这时候命令换做gcc即可.编译器是根据gcc还是g++来确定是按 ...
- IP数据报的格式
1. IP数据报首部的固定部分中的各字段 ①版本:占4位,指IP协议的版本.通信双方使用的 IP协议版本必须一致.日前广泛使用的 IP协议版本号为 4 (即 IPv4). IPv6 目前还处于起步阶段 ...
- sql 行专列 列转行 普通行列转换
转载:http://www.cnblogs.com/newwind521/archive/2010/11/25/1887203.html sql 行专列 列转行 普通行列转换 /* 标题:普通行列转换 ...
- 在Android library中不能使用switch-case语句访问资源ID的原因分析及解决方案
转自:http://www.jianshu.com/p/89687f618837 原因分析 当我们在Android依赖库中使用switch-case语句访问资源ID时会报如下图所示的错误,报的错误 ...
- sql游标的使用入门
游标的理解: 游标其实可以理解成一个定义在特定数据集上的指针,我们可以控制这个指针遍历数据集,或者仅仅是指向特定的行,所以游标是定义在以Select开始的数据集上的 普通的sql语句是面向集合的,游标 ...
- JS中javascript:void(0)真正含义
对于下面的代码,其中void(0)的含义是什么? <a href="javascript:Test();void(0);">hello</a> 其实,Jav ...