Writing finally Blocks

From RAD Studio
Jump to: navigation, search

Go Up to Defining Protected Blocks


An exception handler is code that handles a specific exception or exceptions that occur within a protected block of code. However, there are times when you do not need to handle the exception, but you do have code that you want to execute after the protected block, even if an exception occurs. Typically, such code handles cleanup issues, such as freeing resources that were allocated before the protected block.

By using finally blocks, you can ensure that if your application allocates resources, it also releases them, even if an exception occurs. Thus, if your application allocates memory, you can make sure it eventually releases the memory, too. If it opens a file, you can make sure it closes the file later. Under normal circumstances, you can ensure that an application frees allocated resources by including code for both allocating and freeing. When exceptions occur, however, you need to ensure that the application still executes the resource-freeing code.

Some common resources that you should always be sure to release are:

  • Files
  • Memory
  • Windows resources or widget library resources (Qt objects)
  • Objects (instances of classes in your application)

The following event handler illustrates how an exception can prevent an application from freeing memory that it allocates:

 procedure TForm1.Button1Click(Sender: TObject);
 var
 APointer: Pointer;
 AnInteger, ADividend: Integer;
 begin
   ADividend := 0;
   GetMem(APointer, 1024);{ allocate 1K of memory }
   AnInteger := 10 div ADividend;{ this generates an exception }
   FreeMem(APointer, 1024);{ this never gets called because of the exception}
 end;

Although most errors are not that obvious, the example illustrates an important point: When an exception occurs, execution jumps out of the block, so the statement that frees the memory never gets called.

To ensure that the memory is freed, you can use a try block with a finally block.

Writing a 'finally' Block

Finally blocks are introduced by the keyword finally. They are part of a try..finally statement, which has the following form:

try
{ statements that may raise an exception}
finally
{ statements that are called even if there is an exception in the try block}
end;

In a try..finally statement, the application always executes any statements in the finally part, even if an exception occurs in the try block. When any code in the try block (or any routine called by code in the try block) raises an exception, execution halts at that point. Once an exception handler is found, execution jumps to the finally part, which is called the cleanup code. After the finally part executes, the exception handler is called. If no exception occurs, the cleanup code is executed in the normal order, after all the statements in the try block.

The following code illustrates an event handler that uses a finally block so that, when it allocates memory and generates an error, it still frees the allocated memory:

procedure TForm1.Button1Click(Sender: TObject);
var
APointer: Pointer;
AnInteger, ADividend: Integer;
begin
  ADividend := 0;
  GetMem(APointer, 1024);{ allocate 1K of memory }
  try
    AnInteger := 10 div ADividend;{ this generates an exception }
  finally
    FreeMem(APointer, 1024);{ execution resumes here, despite the exception }
  end;
end;

The statements in the finally block do not depend on an exception occurring. If no statement in the try part raises an exception, execution continues through the finally block.

See Also