Handling Errors and Exceptions
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.
Handling Errors and Exceptions的更多相关文章
- Python Tutorial 学习(八)--Errors and Exceptions
Python Tutorial 学习(八)--Errors and Exceptions恢复 Errors and Exceptions 错误与异常 此前,我们还没有开始着眼于错误信息.不过如果你是一 ...
- 《The Python Tutorial》——Errors and Exceptions 阅读笔记
Errors and Exceptions 官方文档:https://docs.python.org/3.5/tutorial/errors.html python中所有的异常都继承自BaseExce ...
- [译]The Python Tutorial#8. Errors and Exceptions
[译]The Python Tutorial#Errors and Exceptions 到现在为止都没有过多介绍错误信息,但是已经在一些示例中使用过错误信息.Python至少有两种类型的错误:语法错 ...
- Laravel API Errors and Exceptions: How to Return Responses
Laravel API Errors and Exceptions: How to Return Responses February 13, 2019 API-based projects are ...
- 笔记-python-tutorial-8.errors and exceptions
笔记-python-tutorial-8.errors and exceptions 1. errors and exceptions 1.1. syntax errors >& ...
- STL之Errors and Exceptions
Error Handling STL设计的目标是性能最优化,而不是最安全. 错误检查是极其浪费时间的,因此,STL对于错误处理几乎没有做处理,因此,这对STL的使用者的要求就非常高. 为什么不采取错误 ...
- python异常和错误(syntax errors 和 exceptions)
语法错误 语法错误又被称解析错误 >>> for i in range(1..10):print(i) File "<stdin>", line 1 ...
- Python Errors and Exceptions
1. python中的try{}catch{} 2. raise exception 3. try...except ... else.. 4. finally块 python中的异常处理的keywo ...
- Understanding Asynchronous IO With Python 3.4's Asyncio And Node.js
[转自]http://sahandsaba.com/understanding-asyncio-node-js-python-3-4.html Introduction I spent this su ...
随机推荐
- python ORM - sqlalchemy 操作使用
python操作数据库 使用 ORM - sqlalchemy,pymsql 安装: pip install pymsq pip install sqlalchemy 一. '''连接数据库''' ...
- jquery如何获取第一个或最后一个子元素
jquery如何获取第一个或最后一个子元素? 通过children方法,children("input:first-child") $(this).children(" ...
- MySQL-高并发优化
一.数据库结构的设计 1.数据行的长度不要超过8020字节,如果超过这个长度的话在物理页中这条数据会占用两行从而造成存储碎片,降低查询效率. 2.能够用数字类型的字段尽量选择数字类型而不用字符串类型的 ...
- python datetime 时区(timezone) dateutil
记录下python中的时区问题, 代码如下: 包括datetime.datetime对象使用不同的时区,以及在不同时区间转换. from datetime import datetime from ...
- js学习笔记1:语法、数据类型与转换、运算符与运算
注意: 上部代码错误,将停止运行,下部的代码无法显示 typeof 用来定义内容类型,不会输出内容只会输出类型 一.js输出语法 1. 弹窗输出('')内的内容: ...
- 【LOJ】 #2521. 「FJOI2018」领导集团问题
题解 这道题很显然可以想出来一个\(n^2\)的dp,也就是dp[u][i]表示以u为根的子树最大值是i的点集最大是多少(i是离散化后的值) 就是对于每个儿子处理出后缀最大值然后按位相加更新父亲,我们 ...
- 【转】python+django+vue搭建前后端分离项目
https://www.cnblogs.com/zhixi/p/9996832.html 以前一直是做基于PHP或JAVA的前后端分离开发,最近跟着python风搭建了一个基于django的前后端分享 ...
- JDOM读取xml
[摘 要]JDOM是一个开源项目,它基于树型结构,利用纯JAVA的技术对XML文档实现解析.生成.序列化以及多种操作. 一.JDOM 简介 JDOM是一个开源项目,它基于树型结构,利用纯JAVA的技术 ...
- Wannafly挑战赛7 D - codeJan与青蛙
codeJan喜欢观察世界.有一天,codeJan发现一个非常奇怪的现象.有一些年轻的青蛙聚集在一条直线上的某些位置上,同一个位置可能有多个青蛙.这些青蛙每次只会向前跳一米,并且每只青蛙每跳一次都会发 ...
- EOJ 3263 丽娃河的狼人传说
差分约束系统,$spfa$. 首先判断无解,若某个约束的$t$大于区间长度,则一定无解. 否则一定有解,可以得到一系列的不等式: 最终区间和大于等于目前的区间和:$S[R]-S[L-1]≥val$, ...