异常

转载 2006年05月18日 23:17:00

异常的基本思想

  在小型程序中,一旦发生异常,一般是将程序立即中断运行,从而无条件释放所有资源。对于大型程序来说,运行中一旦发生异常,应该允许恢复和继续运行。
  恢复的过程就是把产生异常所造成的恶劣影响去掉,中间可能要涉及一系列的函数调用链的退栈,对象的析构,资源的释放等。继续运行就是异常处理之后,在紧接着异常处理的代码区域中继续运行。
  在C++中,异常是指从发生问题的代码区域传递到处理问题的代码区域的一个对象。

基本思想
 (1)实际的资源分配(如内存申请或文件打开)通常在程序的低层进行。
 (2)当操作失败、无法分配内存或无法打开一个文件时.在逻辑上如何进行处理通常是在程序的高层,中间还可能有与用户的对话。
 (3)异常为从分配资源的代码转向处理错误状态的代码提供了一种表达方式。如果还存在中间层次的函数,则为它们释放所分配的内存提供了机会,但这并不包括用于传递错误状态信息的代码。从中可以看出,C++异常处理的目的,是在异常发生时,尽可能地减小破坏,周密地善后,而不去影响其它部分程序的运行。-这在大型程序中是非常必要的。
  例如普通的程序调用关系,如程序出现异常现象,异常只能在发生的函数中进行处理,无法直接传递到其他函数中,而且善后处理也十分困难。

使用异常的步骤
(1)定义异常(try语句块) 将那些可能产生错误的语句框定在try语句中;
(2)定义异常处理(catch语句块)
将异常处理的语句放在catch块中,以便异常被传递过来时就处理它;
(3)抛掷异常(throw语句)
检测是否产生异常,若产生异常,则抛掷异常。

异常处理机制:
(1)
运行到throw语句时,检测是否发生异常,如果发生异常,则看该异常是否在本函数体中的try语句块中已经定义,如果已经定义,则到本函数中找catch语句,检查是否捕获.如果本函数中的catch语句存在捕获该异常的语句,则执行异常处理语句.如果本函数体中的try语句块中没有定义该异常,或者本函数体中的catch语句不存在捕获该异常的语句,则沿函数链向上传递(其他函数中的try语句定义该函数的异常,具体见以下实例),直到异常被捕获,并执行异常处理语句为止.如果始终没有被捕获,则异常将被系统的terminate()函数调用,后者按常规再调用abort()。你不管,系统就要插手啦!
Example:
void f()

    try { g(); }
    catch(Range)
    { //…… }
    catch (Size)
    { //…… }
    catch (…)
}

void g()
{
    h();
}
void h()
{
try
{
    h1();
}
catch(Size)
{//...
throw 10;
}
catch(Matherr)
{//...
}
}
void h1()
{
//...
throw(Size);
try
{//...
throw Range;
h2();
h3();
}
catch(Size)
{
//...
throw;
}
}

void h2()
{
//...
throw Matherr;
}

void h3()
{
//...
throw Size;
}


函数f()中的catch(...)块,参数为省略号,定义一个"默认"的异常处理程序。通常这个处理程序应在所有异常处理块的最后,因为它与任何throw都匹配,目的是为避免定义的异常处理程序没能捕获抛掷的异常而使程序运行终止。

函数h()中的catch(Size)块,包含有一个抛掷异常语句throw 10,当实际执行这条语句时,将沿着调用链向上传递被函数f()中的catch(...)所捕获。如果没有f()中的catch(...),那么,异常将被系统的terminate()函数调用,后者按常规再调用abort()。

函数h1()中的抛掷throw Size,由于不在本函数的try块中,所以只能沿函数调用链向上传递,结果被h()中的catch(Size)捕获。函数h1()中的抛掷throw Range,在try块中,所以首先匹配try块后的异常处理程序,可是没有被捕获,因而它又沿函数调用链向上,在函数f()中,catch(Range)块终于捕获了该抛掷。函数h1()中的catch(Size)块,包含一个抛掷throw,没有带参数类型,它表示将捕获到的异常对象重新抛掷出去,于是,它将沿函数调用链向上传递,在h()中的catch(Size)块,捕获了该抛掷。

函数h2()中的抛掷throw Matherr,首先传递给h1()中的catch块组,但未能被捕获,然后继续沿调用链向上,在h()中的catch(Matherr)块,捕获了该抛掷。函数h3()中的抛掷throw Size,向上传递给h1()中的catch块组,被catch(Size)块捕获。

使用异常的方法

  可以把多个异常组成族系。构成异常族系的一些实力又数学错误异常族系和文件处理错误异常族系。在C++代码中把异常组在一起有两种方式:异常枚举族系和异常派生层次结构。
例如,下面的代码是一个异常枚举族系的例子:
enmu FileErrors{nonExist,wrongformat,diakSeekError,...};
int f()
{
try{ //... throw wrongFormat;}
catch(FileErrors fe)
{ switch(fe)
{ case nonExist:
//...
case wrongFormat:
//...
case diskSeekError:
//...
}
}
//...
}

在try块中有一个throw,它抛掷一个FileError枚举中的常量。这个抛掷可被catch(FileErrors)块捕获到,接着后者执行一个switch,对照情况列表,匹配捕获到的枚举常量值。上面的异常族系也可按异常派生层次结构来实现,如下例所示:
class FileErrors{};
class NonExist:public FileErrors{};
class WrongFormat:public FileErrors{};
class DiskSeekError:public FileErrors{};
int f()
{ try { //... throw WrongFormat;}
catch(NonExist)
{ //...}
catch(DiskSeekError)
{ //...}
catch(FileErrors)
{ //...}
//...
}
上面的各异常处理程序块定义了针对类NonExist和DiskSeekError的派生异常类对象,针对FileErrors的异常处理,既捕获FileErrors类对象,也捕获WrongFormat对象。异常捕获的规则除了前面所说的,必须严格匹配数据类型外,对于类的派生,下列情况可以捕获异常:
(1) 异常处理的数据类型是公有基类,抛掷异常的数据类型是派生类;
(2) 异常处理的数据类型是指向公有基类的指针,抛掷异常的数据类型是指向派生类的指针。

对于派生层次结构的异常处理,catch块组中的顺序是重要的。
因为"catch(基类)"总能够捕获"throw派生类对象"。所以"catch(基类)"块总是放在"catch(派生类)"块的后面,以避免"catch(派生类)"永远不能捕获异常。




抛出异常和捕获异常的区别

抛出异常:如果程序中出现了异常,没有办法将具体的异常打印出来,不做任何处理   捕获异常:如果程序出现了异常,就能够详细的打印是什么原因导致了异常并且能够做出相应的处理,能够显示详细的Log   如果...
  • hbiao68
  • hbiao68
  • 2013年12月04日 10:14
  • 3875

什么是异常? 在什么情况用异常处理机制?

什么事异常????     异常(exception) 是程序运行过程中发生的事件,  该事件可以中断程序指令的正常执行流程.   异常的处理机制(重点) 1当JAVA程序运行时出现问题时,系...
  • woshi2512901978
  • woshi2512901978
  • 2013年01月17日 23:02
  • 5623

Java受检异常和非受检异常

Java受检异常和非受检异常
  • nlznlz
  • nlznlz
  • 2016年11月22日 00:23
  • 4301

编译时异常和运行时异常的区别

最简单的说法: javac出来的异常就是编译时异常,就是说把源代码编译成字节码(class)文件时报的异常,一般如果用Eclispe,你敲完代码保存的时候就是编译的时候。 java出来的异常就是运...
  • JAVA528416037
  • JAVA528416037
  • 2015年07月01日 09:40
  • 6002

java中一般异常和运行时异常的区别

Java提供了两类主要的异常:runtime exception和checked exception。checked 异常也就是我们经常遇到的IO异常,以及SQL异常都是这种异常。对于这种异常,...
  • u010783583
  • u010783583
  • 2016年08月08日 21:41
  • 264

异常检测原理与实验

最近需要对欺诈报价进行识别处理,简单的模型就是给定很多不同数据集,需要找出每个spu下可能存在的欺诈数据,比如{20,22,30},其中的欺诈数据可能就是30。其实加以抽象,属于异常检测范围。异常检测...
  • xj2419174554
  • xj2419174554
  • 2016年09月14日 22:04
  • 1361

Java常见的异常,Java运行时异常和一般异常的区别

Java常见的异常,Java运行时异常和一般异常的区别 异常和错误二者的不同之处: Exception: 1.可以是可被控制(checked,检查异常) 或不可控制的(unche...
  • u011042188
  • u011042188
  • 2015年06月18日 20:16
  • 2167

软件异常监控

监控系统软件架构的开发设计方案 2016-02-25 10:19:20 监控系统主要用于服务器集群的资源和性能监控以及应用异常和性能监控,日志管理等多维度的性能监控分析。一个完...
  • screaming
  • screaming
  • 2016年06月21日 11:57
  • 739

Spring AOP 抛出增强捕获异常

(一)自定义注解方法         1.自定义注解        @Target(ElementType.METHOD) @Retention(RetentionPolicy.RUNTIME) @I...
  • ab7253957
  • ab7253957
  • 2016年03月17日 09:25
  • 2598

Java常见异常和解决办法

1、java.lang.ArithmeticException 算术运算异常,因为除数为0,所以引发了算数异常 2、Java.lang.StringIndexOutOfBoundsExce...
  • u012630060
  • u012630060
  • 2017年04月27日 21:12
  • 616
内容举报
返回顶部
收藏助手
不良信息举报
您举报文章:异常
举报原因:
原因补充:

(最多只允许输入30个字)