关闭

异常小结

777人阅读 评论(0) 收藏 举报
 
一.        为什么要使用异常:
因为在程序的执行过程中总会遇到许多可以预知或不可以预知的错误事件,例如:由于内存耗尽导致内存分配失败、文件操作失败、内存越界、数组越界、除零等。因此,程序员总需要在程序中不断加入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语言的SHEStructured 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");
}
 
0
0

查看评论
* 以上用户言论只代表其个人观点,不代表CSDN网站的观点或立场
    个人资料
    • 访问:3584次
    • 积分:89
    • 等级:
    • 排名:千里之外
    • 原创:4篇
    • 转载:0篇
    • 译文:0篇
    • 评论:0条
    文章存档