前言
异常有硬件/软件异常之分,在windows系统中使用统一的方式处理硬件/软件异常.
硬件异常,通过cpu产生,例如除0异常,软件异常发生时通过内核函数NtRaiseException发起,windows 系统内核服务异常分发器通过内部函数KiDispatchException对调试器以及异常处理函数进行通知.
异常分发最多二轮过程,{dy}次给调试器,第二次主要给异常过滤代码,在第二次中如果没有找到异常处理函数,但有调试器在附加的情况下,调试器会中断到相应代码行,提示程序员进行调试.
这里会发生内核态与用户态切换,会占用cpu几十个时钟周期.
1 .NET/Java的托管异常是凭借 Win32中的 结构化异常处理机制实现的要捕获异常,必须向系统告知你要处理什么样的异常.
x86系统下异常首先被程序代码(try-catch或者用汇编直接写FS:[0])注册在线程栈中的FS:[0]位置,它指向TEB/TIB({dy}字段ExceptionList) 线程环境块/线程信息块,
这个地址保存被注册过的异常处理函数链表,{zh1}一个函数通常为未处理异常过滤函数.当发生异常时,系统会首先到这里依次寻找对应处理函数.
2 Finally块不一定总是成功当发生StackOverflowException栈溢出异常后的情况,系统会马上终止进程,Finally此时不会被执行。
从.Net 2.0开始,调用Environment.FailFast方法时将在windows事件日志中记录一项信息并立即终止进程,也不会运行finally或者终结器.
3 未处理异常表现 一般windows程序都有统一的默认未处理异常处理过滤函数.
它们通常就是当程序出现错误时,对用户显示出提示对话框,让用户选择终止程序还是调试程序或者发送错误报告.
(具体取决于系统与注册表相关设置)
4 结构化异常中被保护块的执行路线正常结束(自然代码顺序)与非正常结束(异常,return goto break, continue...)
当后者发生时会发生:
全局展开
系统会从调用栈的底部开始向上搜索尚未完成的try块,寻找其中代有finally块的try,并且依次执行它们.{zh1}执行catch异常过滤块.
局部展开(作用:用临时变量存储返回值,再执行finally块.)
当系统因为try代码块中的事件而提前返回而执行finally块时就会发生局部展开,应该辟免在try中使用return语句,否则编译器会生成更多代码.
当代码控制流正常地从try块进入到finally块时,编译器生成的代码是优化的,最少的.
NaN
不必为效率而但心使用异常,异常为编程而生,好的异常处理方式可提高代码开发效率.