首页 > 编程语言 > 详细

C++异常实现与longjmp, setjmp,栈指针EBP, Active Record

时间:2017-03-04 12:57:15      阅读:247      评论:0      收藏:0      [点我收藏+]

这篇讲的不错:

http://blog.csdn.net/smstong/article/details/50728022

 

首先Active Record

技术分享

 

然后EBP,ESP等指针

技术分享

 

2 通过setjmp和longjmp操纵AR,完成任意跳转

setjmp/longjmp主要从嵌套的函数调用中跳出来。

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

jmp_buf jb;
void a();
void b();
void c();

int main()
{
    if(setjmp(jb)==0){
        a();
    }
    printf("after a(); \n");
    return 0;
}
void a()
{
    b();
    printf("a() is called\n");
}
void b()
{
    c();
    printf("b() is called\n");
}
void c()
{
    printf("c() is called\n");
    longjmp(jb, 1);
}

 

3 C语言中模拟异常处理

为了统一处理错误,C++,C#,Java等现代语言引入了异常处理机制。C里面模拟异常的代码大概如下:

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

jmp_buf jb;

void f1()
{
    printf("进入f1()\n");
    if(0/*正确执行*/){ }
    else {
        longjmp(jb,1);
    }
    printf("退出f1()\n");
}
void f2()
{
    printf("进入f2()\n");
    if(1/*正确执行*/) {  }
    else {
        longjmp(jb, 2);
    }
    printf("退出f2()\n");
}

int main()
{
    int r = setjmp(jb);
    if(r==0){
        f1();
        f2();
    }else if(r==1){
        printf("处理错误1\n");
        exit(1);
    }else if(r==2){
        printf("处理错误2\n");
        exit(2);
    }
    return 0;
}

可以推测,
  • throw要负责两件事情:(1)完成跳转;(2)恢复堆栈AR;
  • try则负责保存当前AR

 

4 不要在C++中使用setjmp和longjmp

因为,longjmp的时候,不保证局部对象析构函数的调用

longjmp()跳转前局部对象可能并不会析构(g++),也可能析构(VC++),C++标准对此并无明确要求。这种依赖于具体编译器版本的代码是应该避免的。

而C++本身的throw关键字,却能严格保证局部对象构造和析构的成对调用。

 

5 辩证看待异常处理

已经存在大量没有严格使用异常处理C++函数库和类库,兼容的C库更是没有异常的概念,历史的包袱让C++很难完全采用异常处理。在这个方面,Java和C#从头开始,重要的库都实现了标准的异常处理规范,完全采用异常机制切实可行。

 

有趣的是C++11在标准中删除了异常规范,而且添加了 noexcept关键字来声明一个函数不会抛出异常,可见异常并不是那么受欢迎。

 

然而,C++的STL广泛使用异常,所以实际上使用了STL的C++程序是不可能禁用异常的,要是没有了STL,C++又有什么优势了呢?C++在不断的矛盾冲突中向前发展者。

 

C++异常实现与longjmp, setjmp,栈指针EBP, Active Record

原文:http://www.cnblogs.com/charlesblc/p/6500961.html

(0)
(0)
   
举报
评论 一句话评论(0
关于我们 - 联系我们 - 留言反馈 - 联系我们:wmxa8@hotmail.com
© 2014 bubuko.com 版权所有
打开技术之扣,分享程序人生!