http://delphi.about.com/od/objectpascalide/a/errorexception.htm

Unfortunately, building applications includes coding.

Regardless of how carefully you write/debug your program,

it will be impossible to imagine every situation that can go wrong.

Inexperienced user might, for example,

try to open a nonexisting file or input a bad value into a data field.

Users make mistakes and we should be prepared to handle/prevent these errors

wherever and whenever possible.

Errors, Exceptions?

An exception is generally an error condition or other event

that interrupts normal flow of execution in an application.

Whenever an error results from processing a line of code,

Delphi creates (raises) an object descendent from TObject called the exception object.

Guarded Blocks

An application responds to an exception either by executing some termination code,

handling the exception, or both.

The way to enable error/exception trapping within a given code,

the exception must occur within a guarded block of statements.

The general code looks like:

try
{guarded block of code}
except
on <ESomeException> do
begin
{exception block-handles SomeException}
end;
end;

A try / except statement executes the statements in the guarded block of code.

If the statements execute without any exceptions being raised,

the exception block is ignored, and control is passed to the statement following the end keyword.

Example:

Zero:=;
try
dummy:= / Zero;
except
on EZeroDivide do
MessageDlg('Can not divide by zero!', mtError, [mbOK], ) ;
end;

Protecting Resources

When a section of code acquires a resource, it is often necessary to ensure that the resource is released again

(or you might get a memory leak ), regardless of whether the code completes normally or is interrupted by an exception.

In this case, the syntax usesfinally keyword and looks like:

{some code to allocate resources}
try
{guarded block of code}
finally
{termination blok - code to free resources}
end; { Example } AboutBox:=TAboutBox.Create(nil) ;
try
AboutBox.ShowModal;
finally
AboutBox.Free;
end;

Application.OnException

If your application doesn't handle the error that caused the exception,

then Delphi will use its default exception handler - it will just pop up a message box.

You may consider writing code in the OnException event for TApplication object,

in order to trap errors at the application level.

Break On Exceptions

When building a program with exception handling,

you may not want Delphi to break on Exceptions.

This is a great feature if you want Delphi to show where an exception has occurred;

however, it can be annoying when you test your own exception handling.

On Handling Exceptions in Delphi Exception Handling

No code is error free!

Some code is full of "errors" on purpose :)

What's an error in an application? An error, from my general point of view,

is, for example, the wrongly coded solution to a problem.

Such are logic errors that could lead to wrong function results

where everything seems nicely but the result of the application is completely unusable (i.e. wrong).

With logic errors, application might or might not stop working.

An exception is an exceptional condition.

Exceptions include errors in your code where you try to divide numbers with zero,

or you try using freed memory blocks or you try providing wrong parameters to a function.

An exception in an application is not always an error -

if by error we think on those nasty problems with the program where it stop responding.

Exceptions And The Exception Class

As stated, exception are special conditions that require special handling.

When an error-type condition occurs the program raises an exception.

As suggested by Nick Hodges in Exception Handling for Fun and Profit article,

application writers should trap exceptions, exceptions get raised by components and library code on purpose.

You (as the application writer) handle exceptions, to make your application more error-prone,

to respond to the exceptional condition.

In most cases you will find yourself being the application writer and also the library writer.

So you would need to know how to raise exceptions (from your library) and how to handle them (from your application).

I'm sure we all have dozens of units defining some special-to-me classes, interfaces and alike.

For example, I have a class dealing with PDF documents I'm using in several of my applications.

When I code / edit the class I am the library writer, when I'm using the library I'm the application writer.

Let's take a look at handling exceptions...

The article Handling Errors and Exceptions provides some basic guidelines on

how to guard against errors using try/except/end and try/finally/end protected blocks to respond to or handle exceptional conditions.

A simple try/except guarding blocks looks like:

try
ThisFunctionMightRaiseAnException();
except
{ handle any exceptions raised in ThisFunctionMightRaiseAnException() here }
end;

The ThisFunctionMightRaiseAnException might have, in its implementation, a line of code like

raise Exception.Create('special condition!');

he Exception is a special class (one of a few without a T in front of the name) defined in sysutils.pas unit.

The SysUtils unit defines several special purpose Exception descendants

(and thus creates a hierarchy of exception classes )

like ERangeError, EDivByZero, EIntOverflow, etc.

In most cases the exceptions that you would handle in the protected try/except block

would not be of the Exception (base) class but of some special Exception descendant class defined i

n either the VCL or in the library (you or some other developer coded) you are using.

Handling Exceptions Using Try/Except

To catch and handle an exception type you would construct a "on type_of_exception do" exception handler.

The "on exception do" looks pretty much like the classic case statement :

try
ThisFunctionMightRaiseAnException;
except
on EZeroDivide do
begin
{ something when dividing by zero }
end;
on EIntOverflow do
begin
{ something when too large integer calculation }
end;
else
begin
{ something when other exception types are raised }
end;
end;

Note that the else part would grab all (other) exceptions,

including those you know nothing about.

In general, your code should handle only exceptions you actually know how to handle and expect to be thrown.

Also, you should never "eat" an exception:

try
ThisFunctionMightRaiseAnException;
except
end;

Eating the exception means you do not know how to handle the exception

or you do not want users to see the exception or anything in between.

When you handle the exception and you need more data from it

(after all it is an instance of a class) rather only the type of the exception you can do:

try
ThisFunctionMightRaiseAnException;
except
on E : Exception do
begin
ShowMessage(E.Message);
end;
end;

The "E" in "E:Exception" is a temporary exception variable of type specified

after the column character (in the above example the base Exception class).

Using E you can read (or write) values to the exception object, like get or set the Message property.

Who Frees The Exception?

Noticed how exceptions are actually instances of a class descending from Exception?

The raise keyword throws an exception class instance.

You know that what you create (the exception instance is an object) you also need to free .

If, you as a library writer, create an instance, will the application user free it?

Or, who will?

Delphi magic:

handling an exception automatically destroys the exception object.

This means that when you write the code in the "except / end" block - this block (hm, bad wording)

will release the exception memory.

So what happens if ThisFunctionMightRaiseAnException

actually raises an exception and you are not handling it

(this is not the same as "eating" it)?

How Come My App Does Not Crash When number/0 Is Not Handled?

When an unhandled exception is thrown in your code,

Delphi "magically" handles your exception by displaying the error dialog to the user.

In most cases this dialog will not provide enough data for the user (and finally you)

to understand the cause of the exception.

This is controlled by Delphi's top level message loop

where ALL exceptions are being processed

by the global Application object and its HandleException method.

To handle exceptions globally, and show your own more-user-friendly dialog,

you can write code for the TApplicationEvents.OnException event handler.

Note that the global Application object is defined in the Forms unit.

The TApplicationEvents is a component you can use to intercept the events of the global Application object.

Ok, that's it for now.

Next time I'll go into reraising exception.

最新文章

  1. MCS-51系列特殊功能寄存器(摘录)
  2. Win7以上 32/64位系统隐藏托盘图标
  3. OpenGL 圆角矩形
  4. MongoDb系列
  5. Sed简单入门实例
  6. UIlabel 显示模糊
  7. shell--学习 sed
  8. Java中的main()方法详解
  9. 遍历并修改dictionary的值
  10. Bitmap、BitmapDrawable、BitmapFactory、Matrix类之间的关系
  11. 十二、oracle 数据库(表)的逻辑备份与恢复
  12. Xamarin.Android多窗口传值【1】
  13. 解决vs验证控件报错” WebForms UnobtrusiveValidationMode 需要“jquery”ScriptResourceMapping。请添加一个名为 jquery (区分大小写)的 ScriptResourceMapping”问题
  14. Win10系统BitLocker解锁后再次快速锁定办法
  15. C#如何Json转字符串;字符串转Json;Newtonsoft.Json(Json.Net)
  16. html盒子铺满全屏
  17. Python常用模块—— Colorama模块
  18. /src/struts.xml
  19. EOS开发基础之一:源代码下载与开发环境搭建
  20. spirngcloud文件

热门文章

  1. Tutorial 1: Serialization
  2. nginx 查看当前的连接数
  3. Linux创建ftp并设置权限以及忘记ftp帐号(密码)修改
  4. fedora16下更改网卡名字
  5. ASP连接读写ACCESS数据库实例(转)
  6. **CodeIgniter通过hook的方式实现简单的权限控制
  7. ci框架hook钩子
  8. 用numpy计算成交量加权平均价格(VWAP),并实现读写文件
  9. Weblogic常用监控指标以及监控工具小结
  10. oracle 12C安装问题