C++之setjmp和longjmp不能处理C++的异常(8)---《More Effective C++》
来源:互联网 发布:ios10越狱软件源 编辑:程序博客网 时间:2024/06/11 13:59
setjmp和longjmp是非局部性跳转语句:非局部指的是,这并不类似于普通C语言的goto语句,语句在一个函数内进行跳转,而是在栈上进行跳转,可能跳过很多调用帧,然后返回到当前函数调用路径上的某个函数中去。
使用setjmp和longjmp需要注意的地方:
1)setjmp和longjmp结合使用,有其相应的调用顺序,setjmp在前,longjmp在后,以便可以恢复到先前被保存的“程序执行点”;如果将其顺序颠倒将使得程序的执行变得无法预测,非常容易使得程序崩溃退出;
2)longjmp不仅需要在setjmp调用之后,而且还必须在setjmp的作用域内,其实这个机制的内部是这样实现的:setjmp函数将发生调用的局部环境保存在一个jmp_buf的内存结构中,由于主调函数中对应的内存没有释放,直到函数返回时局部内存就会失效,那么调用longjmp的时候可以根据jmp_buf参数恢复到setjmp的地方然后跳转到setjmp的下一条语句执行,注意setjmp第一次运行的时候返回值为0。
现在我们看看如下例子来了解setjmp和longjmp的运行机制:
#include <iostream>#include <string>#include <csetjmp>using namespace std;static jmp_buf buf;void weiwei(){ cout << "weiwei,you're the only one girl that I have seen who's eyes have all the world I want to live!"<<endl; longjmp(buf, 1);}void Love(){ weiwei(); cout << "I love U,无论多久我等你" << endl;}int main(){ int i = 0; setjmp(buf); Love(); cout << endl; return 0;}
运行结果:
可以判断这段longjmp调用的时候的确跳转到setjmp的后一条语句执行的,由于我们程序中写的是死循环,所以将一直死循环下去。
现在,我们看看为什么不能在C++中利用setjmp和longjmp进行异常处理呢?先来看看如下代码:
1)在longjmp同一个函数作用域中的前面添加类对象:
#include <iostream>#include <string>#include <csetjmp>using namespace std;class MyWeiWei{private: string name;public: MyWeiWei(){ } MyWeiWei(string name) :name(name){ cout << "我是:" << name << ",还望大家多多关照!" << endl; } void show(){ cout << name << endl; } ~MyWeiWei(){ cout << "先下线了,吃饭去了~~~" << endl; }};jmp_buf buf;void weiwei(){ MyWeiWei myWeiWei("现充学妹"); longjmp(buf, 1);}void Love(){ weiwei();}int main(){ int i=setjmp(buf); if (i == 0){ Love(); } cout << "那我等你上线啦!!!" << endl; return 0;}
运行结果:
2)和第一种情况等价,换种形式:
#include <iostream>#include <string>#include <csetjmp>using namespace std;class MyWeiWei{private: string name;public: MyWeiWei(){ } MyWeiWei(string name) :name(name){ cout << "我是:" << name << ",还望大家多多关照!" << endl; } void show(){ cout << name << endl; } ~MyWeiWei(){ cout << "先下线了,吃饭去了~~~" << endl; }};jmp_buf buf;void weiwei(){ longjmp(buf, 1);}void Love(){ MyWeiWei myWeiWei("现充学妹"); weiwei();}int main(){ int i=setjmp(buf); if (i == 0){ //Love(); MyWeiWei myWeiWei("现充学妹"); longjmp(buf,1); } cout << "那我等你上线啦!!!" << endl; return 0;}
运行结果:
3)与longjmp不在同一个函数作用域内:
#include <iostream>#include <string>#include <csetjmp>using namespace std;class MyWeiWei{private: string name;public: MyWeiWei(){ } MyWeiWei(string name) :name(name){ cout << "我是:" << name << ",还望大家多多关照!" << endl; } void show(){ cout << name << endl; } ~MyWeiWei(){ cout << "先下线了,吃饭去了~~~" << endl; }};jmp_buf buf;void weiwei(){ longjmp(buf, 1);}void Love(){ MyWeiWei myWeiWei("现充学妹"); weiwei();}int main(){ int i = setjmp(buf); if (i == 0){ Love(); } else{ cout<<i<<endl; } cout << "那我等你上线啦!!!" << endl; return 0;}
运行结果:
通过这三种对比,我们可以发现,的确setjmp和longjmp不适合处理C++的异常,因为这样有时会使得C++创建的对象的析构函数无法执行。
PS:
int setjmp(jmp_buf env);//返回值,若直接调用返回0,若从longjmp调用返回longjmp中的val值;
void longjmp(jmp_buf env,int val);//调用longjmp返回到setjmp所在的地方,执行setjmp的后一条语句,val值将变成setjmp的返回值,这点在上面程序(3)中得以证明,第二个val的存在是因为对于一个setjmp语句可以有多个longjmp。
- C++之setjmp和longjmp不能处理C++的异常(8)---《More Effective C++》
- C异常处理机制:setjmp和longjmp
- C异常处理机制:setjmp和longjmp
- C异常处理机制:setjmp和longjmp
- C异常处理机制:setjmp和longjmp
- c语言异常处理之longjmp 和 setjmp
- C语言下的setjmp longjmp(C 语言异常处理)
- C语言中利用setjmp和longjmp做异常处理
- C语言中利用setjmp和longjmp做异常处理
- C语言中利用setjmp和longjmp做异常处理
- C语言利用setjmp和longjmp实现异常处理
- c setjmp 和 longjmp
- C setjmp和longjmp
- 详解C的异常处理机制(goto\setjmp longjmp)
- C中的信号处理和函数setjmp()/longjmp()的用法
- C语言实现异常处理(使用 setjmp 和 longjmp 函数)
- c语言的setjmp和longjmp
- 关于c里面的setjmp和longjmp
- 零基础学习GitHub桌面版-2 分支的使用
- AdversarialNetsPapers&Code
- 51Nod 1011 最大公约数GCD
- android -- 重新认识ImageView的几种ScaleType
- C语言之位域
- C++之setjmp和longjmp不能处理C++的异常(8)---《More Effective C++》
- 5分模块开发与实现
- jniLibs
- mysql 中时间日期格式datetime和timestamp比较 以及date_format函数
- AdversarialNetsPapers
- 四种Cast
- Redis集合(set)的命令操作
- Unity入门操作_PlayerPrefs存储_037
- 如何取消eclipse中编辑窗口上方的导航条