Delphi Master Breakthrough (III) Delphi Advanced Step

Source: Internet
Author: User

3rd Chapter exception and error handling

A robust program comes from the correct error handling.




Believe me, there will always be surprises ...

Delphi Master Breakthrough
Just as in real life we can't do everything well, and the code you write can't be right for every line
of the implementation. Life in the face of bad things, handled well, after the storm, the situation will become worse,
Even if it is out of hand, the consequences are difficult. The same is true in program design, so-called robust programs are not error-prone.
program, but a program that can be handled well in the event of an error.
Therefore, error handling has always been an important topic in the field of programming. And exception is object-oriented programming provides
Error-handling solutions. It is a very good tool if you choose OOP and choose Delphi, then
The exception will be your only choice.
To convince you to choose an exception, you need to give some reason. In this chapter, you will get a clear understanding of the anomalies
Bring the benefits.
3.1 Nature of the anomaly
What is an exception? Why do you use it?
In a function-based structure, the function return value is generally used to indicate whether the function was executed successfully and to give the error class
Type and other information. The following form of code is generated:

Nretval: = Somefunctiontoopenfile ();

If Nretval = e_successed then//open successfully
Begin
......
End
else if Nretval = E_file_not_found then//No files found
Begin
......
End
else if Nretval = E_file_format_err then//file format is wrong
Begin
......
End
else then
Begin
......
End

Using methods that return error codes is very common, but there are two problems with using such a method:
(1) resulting in lengthy and complex branching structures (a large number of if or case statements), which makes program flow control become
Complex, which results in the complexity of the testing effort, because the tests need to go through each branch.

50

Exception and error handling
(2) There may be an error that has not been handled (if the function caller does not judge the return value).
Exceptions can be a good solution to the above two issues.
The so-called "exception" refers to an object of an exception class. In Delphi's VCL, all exception classes are derived from Exception
Class. This class declares the general behavior and nature of the exception. Most importantly, it has a Message property that can report the different
frequently occurring causes.
Throws an exception that marks the occurrence of an error. Use the raise reserved word to throw an exception object, such as:
3
Raise Exception.create (′an error occurred!′);
It should be emphasized, however, that exceptions are used to flag errors, but not to cause errors to occur. Produce different
Often only because of encountering raise, at any time, even if no error occurs, raise will cause an exception to occur. Note: Exceptions occur only because of raise, not others!
Once an exception is thrown, the code of the function returns immediately from the exception throw, protecting the sensitive code underneath it from
will be executed. For the function that throws the exception itself, return from the function and return normally from the function by exception (
Line to the end of the function or encounter Exit) is no different, the function code will also pop from the stack, the local simple
Objects (arrays, records, and so on) are automatically cleaned up and recycled.
By throwing exceptions to handle unexpected situations, you can guarantee that all code in the program's main process is available without adding
into a complex judgment statement.
For example, function a throws an exception:

function A (): Integer;
Vat
Pfile:textfile;
Begin
...//Some code
PFile: = Somefunctiontoopenanfile ();
If PFile = Nil Then
Raise Exception.create (′open file failed!′); File open failed throwing exception
Read (PFile, ...); Read the file
...//Other operations on the file, at which point the file pointer is guaranteed to be valid
End

The code for function A makes it easy to handle file open errors. If the file fails to open, it throws a
The Exception class's exception object, the function returns immediately, thus protecting the following operation against the file pointer is not executed. and
The subsequent code can assume that the file pointer is valid, which makes the code more aesthetically pleasing.
Life, we throw away every day garbage will have cleaners to clean up, deal with, otherwise living environment is not everywhere
Filled with rubbish? Similarly, thrown exceptions need to be captured and processed. Suppose function B calls function A, to capture the
This file opens the failed exception and requires a trap to be preset before calling a, which is called
"Try...except block".

51

Delphi Master Breakthrough
First look at the code for function B:

Procedure B ();
Begin
...//Some code
Try
A (); Call a
Somefunctiondependona (); A function that relies on the result of a
Except
ShowMessage (′some error occured′); Hey, I fell in, something happened.
End;
...//continuation of the Code
End

A throws an exception that will be captured by the try...except set by B. Once the exception is caught, it is no longer executed
, instead of immediately jumping to the except block to perform error handling, the process is completed and the entire try block is executed.
After the code. Control over the program flow is left in function B.
If you do not like to pack your own garbage, so in B there is no preset try...except block, then the exception will be
To the caller of B, and if the caller of B is equally irresponsible, the exception will continue to be kicked like a football
To the upper-level caller, and so on. But don't worry, we have a big housekeeper, and we don't have to be hot.
Potato, it will help us clean up, that is--VCL (Delphi's application framework).
Because the VCL framework allows the entire application to be written in a large try...except, whatever
The exception that is not handled will eventually be captured by it and the program flow is returned to the outermost message loop,
No omissions! This is why you will see a lot of Delphi writing, but not professional small software sometimes jump out
A dialog box (shown in 3.1) that reports the error. This situation should be blamed on software writers who are not very
Good handling of errors, but some unknown white anomaly mechanism programmers often blame the Delphi program how can have this
In the case of a sample. In fact, this hint, you should thank the VCL exception mechanism so that the program can continue to run instead of
"Unlawful termination".

Figure 3.1 exception captured by VCL Note: VCL uses a large try...except to wrap up the code!
Therefore, there will be no unhandled exceptions in the VCL framework, in other words, there will be no errors that cannot be handled.
(although I have said the exception is not equal to the error). The capture of exceptions is also very simple, missing a whole bunch of if or

52

Exception and error handling
case, the direction of program control process is very clear, this is the good news for testers.
3.2 Creating your own exception class
The exception mechanism is fully integrated into the object-oriented system, so the exception class and the general class have inherited and Polymorphic
3
Properties. In fact, there is no difference between an exception class and a normal class.
The runtime exception base class for Object Pascal is that all exception classes in EXCEPTION,VCL should derive from it. When
However, the Object Pascal language does not stipulate that it is possible to use raise to throw any pairs of class types other than simple types
Like, Try...except can also capture it, after exception processing will automatically destructor, recycle it, just Exception
Most of the characteristics of the exception are defined. Since other people have prepared a good, complete Exception for us, when
There is no reason not to use it.
Perhaps the reader has also noticed that when all VCL exceptions occur, a warning dialog box pops up with a price
The value of the description of the reason for the occurrence of the exception (positive 3.1, "is not a valid integer value"). This paragraph
The description is very useful for debug work. It is the message property from the Exception class, all exceptions
A description of the error must be given when the class is created. Therefore, when you define and use your own exception class, you also give a
A Message property that is not confusing and understands the cause of the error. Note: Derive your own exception class from Exception!
Here is a sample program to demonstrate how to define, use your own exception class, and its code and executable files can be
The exception directory with the book CD is found.
The program runs after the interface 3.2 shown.

Figure 3.2 Custom Exception class Demo program interface
The operating interface of the program fully embodies the "simplicity" principle described in chapter 1th. There are only 3 of them on the interface
button, first look at the top two (the other "try...finally" button is not explained, left to 3.3 section). A simulation
An error "File not found" occurred while opening the file, and an error occurred "file format was wrong". The so-called simulation
An error occurs when an exception is thrown without a real error, causing the compiler to think that an error has occurred,
When you click the two buttons, the program throws the corresponding exception respectively.
The first is to define the exception classes that correspond to the two types of errors. They are defined and implemented in the Exceptionclass.pas unit
In The Unit code list is as follows:

53

Delphi Master Breakthrough
Unit Exceptionclass;

Interface

Uses sysutils, Dialogs;

Type

Efileopenfailed = Class (Exception)//define a common exception class that fails to open a file
Public
Procedure Warning (); Virtual Abstract
End

Efilenotfound = Class (efileopenfailed)//fine-grained file open failed exception
Public
Procedure Warning (); Override
End

Efileformaterr = Class (efileopenfailed)//fine-grained file open failed exception
Public
Procedure Warning (); Override
End

Implementation

{Efilenotfound}

Procedure efilenotfound.warning;
Begin
ShowMessage (' It's unbelievable that I can't find the file! ‘);
End

{Efileformaterr}

Procedure efileformaterr.warning;
Begin
ShowMessage (' More incredible, the file format is wrong! ‘);
End

End.

We first defined a flag to open the file failed exception base class efileopenfailed, and gave it a declaration of a

54

Exception and error handling
Abstract method Warning. It then refines the cause of the error, thus deriving two exception classes--efilenotfound,
Efileformaterr, they all implement the Warning method concretely.
In the main form (FORM1) of the application, define a simulateerror () that simulates an error and throws an exception
method to simulate an error occurrence, throw an exception.
Then define a ToDo () method to invoke the Simulateerror () that throws the exception and capture it with a Try
For exception handling.
3
Finally, in the OnClick () event of two buttons, call the ToDo () method.
The code listing is as follows:

Unit Unit1;

Interface

Uses
Windows, Messages, sysutils, variants, Classes, Graphics, Controls,
Forms, Dialogs, Stdctrls;

Type
TForm1 = Class (Tform)
Button1:tbutton;
Button2:tbutton;
Label1:tlabel;
Button3:tbutton;
Procedure Button1Click (Sender:tobject);
Procedure Button2click (Sender:tobject);
Procedure Button3click (Sender:tobject);
Private
{Private declarations}
Public
{Public declarations}
Procedure Simulateerror (Button:tobject);
Procedure ToDo (Button:tobject);
End

Var
Form1:tform1;

Implementation

Uses Exceptionclass;


55

Delphi Master Breakthrough
{$R *.DFM}

Procedure Tform1.simulateerror (Button:tobject);
Begin
If Button = Button1 Then
Raise Efilenotfound.create (' File not Found ')
else if Button = Button2 Then
Raise Efileformaterr.create (' File Format Error ')
else//Button = Button3
Raise Exception.create (' unknonw Error ');
End

Procedure Tform1.button1click (Sender:tobject);
Begin
ToDo (Sender);
End

Procedure Tform1.button2click (Sender:tobject);
Begin
ToDo (Sender);
End

Procedure Tform1.todo (Button:tobject);
Begin
Try
Simulateerror (Button)
Except
On e:efileopenfailed do
E.warning ();
On E:exception do
ShowMessage (E.message);
End
End

Procedure Tform1.button3click (Sender:tobject);
Var
Astream:tmemorystream;
Begin
Astream: = Tmemorystream.create ();

Try
Simulateerror (Sender);

56

Exception and error handling
Finally
Astream.free ();
End
End

End.
3
After the program runs, the ToDo method is called when you click one of the two buttons above the interface. While in ToDo
method, because Simulateerror is called and throws an exception, although there is no real open file error,
But it does throw an exception. This again means that the exception is used to flag the error, not the same as the error.
Program, we define a flag to open file failed exception base class efileopenfailed, and two factions
--efilenotfound and Efileformaterr of the abnormal class. This defines the exception class framework and gives the error handling section A
To have more flexibility. This is another boon to us for polymorphism. The "fine" of the exceptions to be captured is freely selectable.
Degree ". That is, if the user is very concerned about the specific cause of the error, each of the lowest-level exceptions can be captured
Class, and if you are only concerned about whether an open file error has occurred, you can only capture the efileopenfailed class;
The heart is only if there is an error, then just capture the Exception on the line.
In addition to the Simulateerror call, the try...except is set, and the exception it throws is captured.
The processing code of the exception class with "precision" and "finer" is placed before the exception class with "precision" being "thicker"
and the code behind. If the opposite is true, all exceptions are caught by exception's processing code, while the other exceptions
The processing code of the class will never have a chance to execute.
The Exception program demonstrates the definition, implementation, and use of a very small, custom exception class framework. "Sparrow
Although small, perfectly formed, it gives a way to capture and handle errors in their own programs.
3.3 try...finally
It is now known that throwing an exception in a function will result in a normal return of the function, so the local simplicity in the function stack
Objects (arrays, records, and so on) are freed. It is also known that all of the class objects in object Pascal are
is constructed in the heap, the compiler does not automatically call their destructors when exiting the function, so how to ensure that all the offices
Can a class object also be released?
Object Pascal introduces a unique try...finally to solve this problem.
Try...finally blocks help you ensure that some important code can be executed, whether or not an exception occurs, which
The code is between finally and end.
Open the Exception program again, and now take a look at the 3rd button that is useless. Add a for its Click event
The following code:

Procedure Tform1.button3click (Sender:tobject);
Var
Astream:tmemorystream;

57

delphi   master breakthrough      
Begin
  astream: = Tmemorystream.create ( );
 
 try
   simulateerror (self);
 finally
   astream.free ();
 end;
End;
 
It first creates a memory stream object to impersonate the function to request some system resources. The Simulateerror method is then called
, but this time Simulateerror throws a Exception exception. However, the destruction of the
memory stream object is placed in the finally protection, thereby guaranteeing the release of the object. You can step through the
trace yourself, whether in the case of an exception (that is, call simulateerror), or if you exit normally (not
call simulateerror or change the simulateerror call to exit). Astream.free () will get
to execute. The
has try...except and try...finally at the same time, should say is Delphi Programmer's kind of lucky, is fortunate.
Just, we want more, will want to have
 
Try
  
except
  
finally
 
Such a structure is not yet satisfied. Although you can use
 
Try
 try
   
 except
   
 end
finally
  
End;
 
to replace, but clearly not as desirable as the structure of aesthetics and elegance. This cannot but say is a kind of regret, let us send the hope
to look at the next Delphi version!
 
• 58 •

Exception and error handling
3.4 Constructors and exceptions
This topic is often mentioned in the C + + community, and no one in the Delphi community has ever noticed it,
The fact that Delphi programmers do not have to be concerned about this problem is due to the language's nature. But I think that Delphi programmers should also
3
Knowing the question, knowing what the language provides for us makes it so easy for us to ignore it. is the
"The blessing of the body in the blessing."
We know that the constructor of a class has no return value, so if the constructor constructs an object that fails, it cannot be
Can rely on the return error code to resolve. So, how does it fail to identify the constructor in the program? The most "standard"
The way is: throw an exception.
Constructor failed, which means that the construction of the object failed. So after throwing an exception, the "Half-dead" pair
What is the elephant going to do with it?
Here, it is necessary for the reader to have an understanding of how C + + handles this situation.
In C + +, the destructor is not called after the constructor throws an exception. This approach is justified, because
The object is not fully constructed.
If the constructor has done something such as allocating memory, opening files, and so on, the C + + class needs to have its own
Members to remember what actions have been made. Of course, this is very cumbersome for the class's implementation. Therefore, General C + +
The class's implementation avoids throwing an exception in the constructor, which can provide a member function such as Init and UnInit.
They are called by the client of the constructor or class to handle the failure of the initialization. And each of the classic C + +
The solution provided is to use smart pointers (STL's standard class auto_ptr).
In Object Pascal, the problem becomes very simple, and programmers do not have to bother with it. If the Object
Pascal's class throws an exception in the constructor, the compiler automatically calls the class's destructor (because the destructor does not
Allows overloading to ensure that only one by one destructors are available, so the compiler does not confuse multiple destructors.
The destructor typically analyzes the constituent member object, and the free () method guarantees that the nil object (that is, not yet created
Object) calls the destructor, so that the code is simple and beautiful, but also to ensure security.
The following program demonstrates the processing method that the Object Pascal compiler does after throwing an exception in the constructor.
First define the Tmyclass:

Type
Tmyclass = Class
Private
Fstr:pchar; string pointers
Public
Constructor Create ();
destructor Destroy (); Override
End

Then implement Tmyclass and let it throw an exception in its constructor:

59

Delphi Master Breakthrough
Constructor Tmyclass.create ();
Begin
FSTR: = Stralloc (10); allocating memory for string pointers in constructors
Strcopy (fstr, ' Abcdefghi ');
Raise Exception.create (' Error '); Throw an exception, no reason
End

destructor Tmyclass.destroy ();
Begin
Strdispose (FSTR); Freeing memory in destructors
Writeln (' free Resource ');
End

Finally, write the code for the program's main process. An instance of the Tmyclass class is first created in the main process:

Var
Obj:tmyclass;
I:integer;
Begin
Try
OBJ: = Tmyclass.create ();
Obj.free (); Destructors are not called, but when an exception occurs, the compiler automatically calls the destructor
Writeln (' succeeded ');
Except
OBJ: = nil;
Writeln (' Failed ');
End

Read (i); Pause the screen to observe the running results
End.

In this code, it is troublesome to create an instance of the Tmyclass class because the Tmyclass constructor throws
An exception, but the result of this code execution is:

Free Resource
Failed

"Free Resource" appears, stating that the destructor was called after an exception occurred. And this is where the construction letter
After the number throws an exception, the compiler calls the result of the destructor automatically.
Therefore, if the author of the class's description document or class tells you that the class's constructor might throw an exception, then
Remember to wrap it with try...except!

60

Exception and error handling
C + + and Object Pascal have different ways of handling the exception after the constructor is thrown, which is actually the two languages
The embodiment of design thought. C + + adhering to the style of language, focus on efficiency, all to the programmer to master, the compiler does not
To do extra action; Object Pascal inherits Pascal's style, pays attention to the aesthetic meaning of the program, and compilers help programmers
Complete the complex work.
3.5 Summary 3
Exceptions are a very good tool for object-oriented programming, and it is a pity to not use them. But, as everything
There is a "degree", misuse of the exception is also undesirable. The use of exceptions is not without cost, it increases the burden of the program,
There is a big difference between writing several try...except and writing thousands of try...except.
At the same time, there is no need to be overly afraid of the burden it brings. In fact, since the use of Delphi, in fact, has been
After the use of the exception, perhaps just do not know. Listen to Chalie Calverts's advice: "In the seemingly useful
Time, you should use try...except blocks. But try to keep your enthusiasm for the technology not too much. "

Delphi Master Breakthrough (III) Delphi Advanced Step

Contact Us

The content source of this page is from Internet, which doesn't represent Alibaba Cloud's opinion; products and services mentioned on that page don't have any relationship with Alibaba Cloud. If the content of the page makes you feel confusing, please write us an email, we will handle the problem within 5 days after receiving your email.

If you find any instances of plagiarism from the community, please send an email to: info-contact@alibabacloud.com and provide relevant evidence. A staff member will contact you within 5 working days.

A Free Trial That Lets You Build Big!

Start building with 50+ products and up to 12 months usage for Elastic Compute Service

  • Sales Support

    1 on 1 presale consultation

  • After-Sales Support

    24/7 Technical Support 6 Free Tickets per Quarter Faster Response

  • Alibaba Cloud offers highly flexible support services tailored to meet your exact needs.