当我们运行的结果和预期不一致的情况下,就会导致异常,我们常常会认为异常是系统带给我们的,其实不是,异常是写代码类库的人会认为我们写的这段代码有可能会出现错误,就会给我们抛出异常,让我们去注意然后去解决。
什么是异常?
- 运行时出现错误或BUG
- 编写代码预期条件和实际条件不吻合
- 异常机制是为了保证程序一直正常运行
在c#中的异常处理
先预热举一个小例:
在c#中,假如我们程序运行到了 Convert.ToInt32("123")→1*100+2*10+3,当如果是Convert.ToInt32("abc")就会出现错误,因为无法将字符类型转换成Int类型。
因为系统类库在程序员在封装这个方法时,有可能是以这么一种形式进行编写:
当我们在这个环境下就行运行程序,系统就会抛出异常
-> 如果异常不处理程序就会死掉
1 public void Func1() 2 { 3 Func2(); 4 } 5 6 try 7 { 8 // 可能出现异常的代码 9 // 出现异常,其后的代码不再执行 10 // 直接跳转到catch 11 } 12 catch(Exception ex) 13 { 14 // 写入日志,处理异常后的首尾工作 15 }
如果在程序中异常如果没有得到处理,就会继续往上提交直至异常被处理,如果最终没被处理,系统就会报错。
在Java中的异常处理
-
throws用在方法声明中,表明当前方法在运行时会有异常抛出,需要在调用该方法的时候注意控制异常。
-
throw用在方法体内,手动制造一个异常,中断代码的继续执行。
-
try-catch-finally是一起使用的。
当某段代码在运行期间可能会发生异常而终止执行时,使用。
结构为:
try
{
//可能发生异常的代码
}
catch (异常类型 )
{
//异常发生时的处理方式
}
finally
{
//其他必须执行的语句
}
当try语句块中的代码在执行时发生异常,就会被catch捕获,进入catch语句块进行处理,如果没有发生异常就继续执行,finally语句块中的代码是一些必须执行的语句,这里的代码无论try中是否发生异常都会被执行。
在C语言,汇编语言中的异常处理
所有东西都是通过返回值来进行的,没有异常的概念,而是通过返回int类型的整数来确定程序是否出现了问题。
举一个简单例子:
在c语言中嵌入了汇编程序来处理程序触发的windows异常处理.程序中加了注释,问题就在里面:
__asm{
/*假设程序运行到此处,几个寄存器值分别为:eax=1,ebx=2;ecx=3;edx=4,edi=1000,esi=1100,ebp=1024,esp=1300*/
push offset Error;
push fs:[0];
mov fs:[0],esp;
mov [eax],ebx;
/*程序在这里触发异常*/ Error:/*解发异常后陷阱处理程序会运行到此*/
lea eax,[esp+0xc];
mov eax,[eax];
add eax,184;
mov [eax],
0ffset RUN_001; xor eax,eax;
/*设置运行RUN_001*/ ret; RUN_001:
/*程序运行到这里,则:各各寄存器的值是否是:eax=1?,ebx=2?,ecx=3?,edx=4?,edi=1000?,esi=1100?,ebp=1024?,esp这个值肯定是1308无疑问!
就是当我们拦截到自己程序异常后,各各寄存器值是否恢复?这个不一定,主要还是看你的异常处理例程是怎么处理的。对于可修复错误,或许事可以从断点处继续执行。这时候程序上下文被保存,用于返回现场。但是对于致命错误,程序直接退出。各寄存器的值都是不可预知的。