Windows 结构化异常与 C / C++异常的一些事

一直以来对“异常”以及相关的知识很模糊,这次做个整理,回答几个基本问题以帮助对“异常”的理解:

  • C语言的异常
  • C语言版的try/catch: setjmp, longjmp
  • C++的异常(try/catch)
  • Windows 结构化异常,以及与C++标准异常的联系(__try/__except与try/catch)
  • 在Windows API 与标准C++代码混用的项目中,如何较好的捕捉所有异常?

C语言的异常

C语言本身对异常处理比较少,当异常发生时,往往有以下方式:

1. exit()与abort()。

使用C库函数exit()和abort() 强行终止程序运行。

exit() - 通常表示程序正常退出。exit()退出之前会做一些清理工作,比如销毁static变量,刷一下缓冲区(不知道是否指文件系统缓冲区?),关闭IO通道,然后结束程序。用户还可通过at_exixt(your_exit_fun)设置自己的退出函数,程序exit()时会调用,通过your_exit_fun()做自定义的清理工作,比如把文件写回磁盘。

abort() - 该函数被调用通常表示出现了无法处理的异常,直接终止程序。它不像exit()那样做清理工作。


2.使用assert(断言)宏调用,位于头文件<assert.h>中,当程序出错时,就会引发一个abort()。


3.使用errno全局变量,由C运行时库函数提供,位于头文件<errno.h>中。


4.使用goto语句,当出错时跳转。


5.使用setjmp, longjmp进行异常处理。

 

C语言版的try/catch: setjmp, longjmp

不像goto只能实现函数内跳转,setjmp / longjmp一起用可以跨函数跳转。

setjump, longjmp的原理是先通过setjump设置一个跳转点,其实就记录下跳转点的栈信息,然后通过longjmp 来恢复该栈点信息,从而跳转到setjump事先定义的跳转点上执行。

函数定义:

int setjmp(jmp_buf env);
void longjmp(jmp_buf env, int val);

setjmp() 接受一个jmp_buf类型参数,当显式调用它时,当前栈信息会被记录入该jmp_buf;而longjmp被调用时,并指定同一个jmp_buf作为参数,就会跳转到该栈点上执行,而第二参数val会变成setjmp第二返回时的返回值!这可能是搞晕人的地方:


为什么setjmp会返回两次?


看它的使用,或者就理解了:

#include <cstdio>
#include <cstdlib>
#include <setjmp.h>

jmp_buf jmpbuffer;

void raise_exception(void)
{
	printf("raise_exception()\n");
	longjmp(jmpbuffer,1);
}

int main(int arg
  • 0
    点赞
  • 4
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值