异常小结

 
一.        为什么要使用异常:
因为在程序的执行过程中总会遇到许多可以预知或不可以预知的错误事件,例如:由于内存耗尽导致内存分配失败、文件操作失败、内存越界、数组越界、除零等。因此,程序员总需要在程序中不断加入if语句,来判断是否有异常出现,如果有,就必须要及时处理。这样一来,程序的可读性就差了很多,总有许多与真正工作无关的代码。
使用C++的异常处理机制有以下的优点:
1.   把错误处理和真正的工作分开;
2.   代码更容易组织,更清晰,复杂的工作任务更容易实现;
3.   安全,不至于一些小的疏忽而使程序以外崩溃了。
 
二.        常用的异常:
1. C++ 异常处理机制:try-catch
(1)        概念:关键字try表示定义一个受监控、受保护的程序代码块;关键字catch与try遥相呼应,定义当try block(受监控的程序块)出现异常时,错误处理的程序模块,并且每个catch block都带一个参数,这个参数的数据类型用于异常对象的数据类型进行匹配;而throw则是检测到一个异常错误发生后向外抛出一个异常事件,通知对应的catch程序块执行对应的错误处理。
(2)   示例:
#include "stdafx.h"
using namespace std;
 
int _tmain( int argc, _TCHAR* argv[])
{
cout << "In main" << endl;
try
{
cout << "In try block, before throw a exception!" << endl;
throw 1;
cout << "In try block, after throw a exception!" << endl;
}
catch (int& value)
{
cout << "In catch block, the exception value is: " << value << endl;
}
 
cout << "Press any key to exit!" << endl;
getchar();
return 0;
}
结果显示:
In main
In try block, before throw a exception!
In catch block, the exception value is: 1
Press any key to exit!
 
#include "stdafx.h"
using namespace std;
 
int _tmain( int argc, _TCHAR* argv[])
{
cout << "In main" << endl;
try
{
cout << "In try block, before throw a exception!" << endl;
int* p = NULL;
*p = 13;
cout << "In try block, after throw a exception!" << endl;
}
catch (...)
{
cout << "In catch block, find exception" << endl;
}
 
cout << "Press any key to exit!" << endl;
getchar();
return 0;
}
结果显示:
In main
In try block, before throw a exception!
In catch block, find exception
Press any key to exit!
 
 
2.  C 语言的SHE Structured Exception Handling 结构化异常处理 ):与C++的异常处理机制相对应,C语言提供了__try、__except、__finally、__leave组成的结构化异常处理。
(1)        try—except:程序在执行受监控的代码(即__try{}中的代码)的过程中,如果没有出现异常,则转入__except(){}之后的代码模块中继续执行;否则,如果出现异常,那么控制流将进入__except后面的表达式中,先计算这个表达式的值,再根据这个值来作出相应的处理,这个值有3种情况:
(a)        EXCEPTION_CONTINUE_EXECUTION -1 :异常被忽略,控制流将在异常出现的点后继续执行;
(b)        EXCEPTION_CONTINUE_SEARCH (0):异常不被识别,也即当前的__except模块不是这个异常错误所对应的正确的异常处理模块,系统将继续到上一层的try-except域中继续查找一个恰当的__except模块。
(c)        EXCEPTION_EXECUTE_HANDLER (1):异常已经被识别,控制流将进入到__except模块中。
 
示例 1
#include "stdafx.h"
 
int _tmain( int argc, _TCHAR* argv[])
{
puts("hello");
 
__try
{
puts("In try");
int* p = NULL;
*p = 45;
puts("after exception!");
}
__except (puts("In filter"), 1)
{
puts("In except");
}
 
puts("world");
getchar();
return 0;
}
结果如下:
hello
In try
In filter
In except
World
可见,并没有执行异常点之后的代码,而是进入了 __except之后的异常处理。
 
示例 2:
#include "stdafx.h"
 
int _tmain( int argc, _TCHAR* argv[])
{
int j, zero;
 
puts("hello");
 
__try
{
puts("In try");
zero = 0;
j = 10;
j = 45 / zero;
printf("can go to here? j=%d /n", j);
}
__except(puts("In filter"), zero = 1, -1)
{
puts("In except");
}
 
puts("world");
 
puts("Press any key to continue...");
getchar();
return 0;
}
结果显示如下:
hello
In try
In filter
Can go to here? j = 45
World
可见,并没有处理_except后面的模块,而是继续执行异常点之后的代码。
 
(2)        try-finally:用于有效地保证资源的清除。
(a)        不管在任何情况下,在离开当前的作用域时,finally块区域内的代码都会被执行到;
(b)        try-finally语句的作用相当于面向对象中的析构函数;
(c)        使用__leave来代替try块中的goto和return:__leave的作用是离开当前的try块。
示例1:
#include "stdafx.h"
#include <stdio.h>
 
void test()
{
puts("hello");
__try
{
int* p;
puts("In try");
 
// 直接跳出当前的__try作用域
__leave;
puts("after __leave");
p = 0;
*p = 25;
}
__finally
{
// 这里会被执行吗?当然
puts("In Finally");
}
 
puts("world");
}
 
void main()
{
__try
{
test();
}
__except(1)
{
puts("In except");
}
 
puts("press any key to continue...");
getchar();
}
结果显示如下:
hello
In try
In finally
World
可见,使用 __leave跳出当前的try块之后,后面的语句没有被执行,但是,还是执行了finally块!使用goto和return语句代替__leave,效果一样,还是会执行finally块。
示例 2:
#include "stdafx.h"
 
#include <stdio.h>
#include <stdlib.h>
 
void main( void )
{
__try
{
char* p1;
char* p2;
 
__try
{
puts("do p1 malloc");
p1 = ( char*)malloc(10);
puts("do p2 malloc");
p2 = NULL;
*p2 = 'a';
puts("After exception!");
}
__finally
{
if(p1)
{
free(p1);
puts("free p1");
}
if (p2)
{
free(p2);
puts("free p2");
}
}
}
__except(puts("In except finter"), 1)
{
puts("In exception!");
}
 
puts("press any key to continue...");
getchar();
}
结果显示如下:
do p1 malloc
do p2 malloc
In except filter
Free p1
In except
 
示例3:msdn的例子
#include <stdio.h>
#include <windows.h> // for EXCEPTION_ACCESS_VIOLATION
#include <excpt.h>
int filter(unsigned int code, struct _EXCEPTION_POINTERS *ep) {
   puts("in filter.");
   if (code == EXCEPTION_ACCESS_VIOLATION) {
      puts("caught AV as expected.");
      return EXCEPTION_EXECUTE_HANDLER;
   }
   else {
      puts("didn't catch AV, unexpected.");
      return EXCEPTION_CONTINUE_SEARCH;
   };
}
int main()
{
   int* p = 0x00000000;   // pointer to NULL
   puts("hello");
   __try{
      puts("in try");
      __try{
         puts("in try");
         *p = 13;    // causes an access violation exception;
      }__finally{
         puts("in finally. termination: ");
         puts(AbnormalTermination() ? "/tabnormal" : "/tnormal");
      }
   }__except(filter(GetExceptionCode(), GetExceptionInformation())){
      puts("in except");
   }
   puts("world");
}
 
  • 1
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值