当前位置:主页   - 电脑 - 程序设计 - Delphi
沉默的异常--Delphi帮助寻宝之一
来源:网络转载   作者:未知   更新时间:2008-11-12
收藏此页】    【字号    】    【打印】    【关闭

~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~

更新历史:No.2 更新时间:2001-10-21 02:42 更新人员:Musicwind® 更新备注:修改格式。 更新历史:No.1 更新时间:2001-10-19 21:15 更新人员:Musicwind® 更新备注:创建。

~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~

前言:沉浸于Delphi 已逾三载,可是每每翻阅Delphi 的帮助文档,还是会有许多收获,于是不免感慨Delphi 的博大!在惭愧之余,将些许心得和收获整理,与诸位当中如我般自大而学识尚浅者,共勉。

1. 什么是沉默的异常?(为什么不是沉默的羔羊?;- ))

沉默的异常,即Slient Exceptions ,指的是在缺省情况下不会出现讨厌的消息提示框的异常类型:EAbort 。在Object Pascal中,异常类EAbort 是所有沉默的异常类的祖先类(而EAbort是继承Exception而来)。引发(Raise)一个EAbort将导致一个执行模块的停止,直到有最外层的异常处理模块截获它,但是并不因此出现带有红色停止标志的消息框。参考如下代码:

try

ShowMessage('Hello1');

Raise EAbort.Create('Abort it');

ShowMessage('Hello2');

except

on E: Exception do

showmessage('On Exception');

end;

执行结果显示两个消息框,一个是”Hello1”,另一个是”On Exception”。这表明,EAbort确实发挥了作用,因为它跳过了”ShowMessage(‘Hello2’)”这个语句;同时,没有出现”Abort it”的消息框,也证实了EAbort异常类的不出现对话框的特点(在设计期间也是如此);并且,消息框”On Exception”表明,虽然可能EAbort是个不同于普通异常的异数,但这并不妨碍我们沿用老的Try-Except语句来捕获它。

2. 为什么要用EAbort

EAbort在某些场合下很有用。比如当我们需要终止某项操作,而又不希望让用户察觉(不想让他们看到默认的异常消息框)。当然,要达到相同的效果,使用普通的异常也可以做到(比如使用Try-Except句型,将代码放在Try段,需要终止操作则raise一个异常,而在Except段不写任何代码),但是这一切没有比使用EAbort来的简单又直接。

3. 有什么简便一点的吗?——使用Abort 过程

SysUtils单元中定义的一个过程Abort可以让我们方便的使用EAbort。查看Abort的实现源码:

procedure Abort;

function ReturnAddr: Pointer;

asm

MOV EAX,[EBP + 4]

end;

begin

raise EAbort.Create(SOperationAborted) at ReturnAddr;

end;

这里的SOperationAborted通常就是” Operation aborted”。 4. 揭开面纱——实现原理

也许各位和我一样,对于EAbort为什么是沉默的感到好奇。Delphi在其内部,究竟对EAbort做了什么手脚呢?让我们一起来看个究竟。

打开一个新的工程,点击Find in Files,输入”EAbort”关键字,然后选中Search in Directories单选框,并将Search Directory Options中的File Mask编辑框设置

为Delphi源码所在的目录名(比如我的是:D:\Program Files\Borland\Delphi6\Source\),同时别忘记给Include SubDirectory打勾。最后,点击”OK”开始搜索。 结果我们发现Delphi源码中与EAbort有瓜葛的达17

处之多。除去Sysutils单元中两处对EAbort的声明以及部分注释语句,我们发现绝大多数代码类似于: if ExceptObject is EAbort then

以及:

if not (E is EAbort) then

等等。

无一不是根据RTTI 来对EAbort特殊对待的——原来EAbort的实现就这么简单!

值得关注的两个单元是:Forms(Linux版本为QForms)和AppEvnts,在前者的代码中我们更不难找到问题的答案。参见Delphi源码:

procedure TApplication.HandleException(Sender: TObject);

begin

if GetCapture <> 0 then SendMessage(GetCapture, WM_CANCELMODE, 0, 0);

if ExceptObject is Exception then

begin

if not (ExceptObject is EAbort) then

if Assigned(FOnException) then

FOnException(Sender, Exception(ExceptObject))

else

ShowException(Exception(ExceptObject));

end else

SysUtils.ShowException(ExceptObject, ExceptAddr);

end;

5. Abort 与Break 和Exit 之区别

Abort和Break和Exit有些相似,又很不同。Break用来在循环语句中跳出一层循环。Exit用来跳出当前执行的函数体(或过程体)。Abort可以让你跳出一层或者多层代码段,直到有异常捕获的代码将它捕获。

6. 自定义沉默的异常

与声明一个普通异常类的子类相同,只需将EAbort及其子类作为祖先类即可:

TMyException = Class(EAbort);

TNextException = Class(EAbort);

等等。

Musicwind®@HangZhou.Zhejiang.China

2001-10-20

更多文章 [ 文终]

其它资源
来源声明

版权与免责声明
1、本站所发布的文章仅供技术交流参考,本站不主张将其做为决策的依据,浏览者可自愿选择采信与否,本站不对因采信这些信息所产生的任何问题负责。
2、本站部分文章来源于网络,其版权为原权利人所有。由于来源之故,有的文章未能获得作者姓名,署“未知”或“佚名”。对于这些文章,有知悉作者姓名的请告知本站,以便及时署名。如果作者要求删除,我们将予以删除。除此之外本站不再承担其它责任。
3、本站部分文章来源于本站原创,本站拥有所有权利。
4、如对本站发布的信息有异议,请联系我们,经本站确认后,将在三个工作日内做出修改或删除处理。
请参阅权责声明