Finally ブロックの記述

提供: RAD Studio
移動先: 案内検索

保護ブロックの定義 への移動


例外ハンドラは、保護されているコード ブロック内で発生する特定の例外(複数の場合あり)を処理するコードです。 一方、たとえ例外が発生しても、例外を処理する必要はないものの、保護ブロックの後に実行したいコードがある場合もあります。 通常、そのようなコードでは、保護ブロックの前に割り当てられたリソースの解放など、クリーンアップの問題を処理します。

アプリケーションでリソースを割り当てる場合、finally ブロックを使用することで、たとえ例外が発生してもそのリソースを確実に解放することができます。 したがって、アプリケーションでメモリを割り当てる場合は、このメモリが最終的に必ず解放されるようにすることができます。 アプリケーションでファイルを開く場合は、後でそのファイルを確実に閉じることができます。 普通の状況では、割り当てと解放の両方のコードをアプリケーションに含めることで、アプリケーションで割り当てたリソースを確実に解放できます。 しかし、例外が発生する場合でも、リソースを解放するコードがアプリケーションで必ず実行されるようにする必要があります。

必ず解放しなければならないリソースとしては、一般に以下のものがあります。

  • ファイル
  • メモリ
  • Windows リソースまたはウィジェット ライブラリ リソース(Qt オブジェクト)
  • オブジェクト(アプリケーション内のクラスのインスタンス)

次のイベント ハンドラでは、割り当てたメモリを例外のためアプリケーションで解放できなくなる例を示しています。

 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;

ほとんどのエラーはこれほど明白ではありませんが、この例は重要な点を明らかにしています。つまり、 例外が発生すると、実行はブロック外にジャンプするので、メモリを解放する文は決して呼び出されないということです。

メモリを確実に解放するには、try ブロックを finally ブロックと一緒に使用することができます。

'finally' ブロックを書く

finally ブロックは finally キーワードで始まります。 このブロックは try..finally 文の一部であり、次のような形式になっています。

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

try..finally 文では、たとえ try ブロックで例外が発生しても、アプリケーションは finally 部の文を必ず実行します。 try ブロック内のコード(または try ブロック内のコードで呼び出されたルーチン)で例外が発生した場合、実行はそこで停止します。 例外ハンドラが見つかったら、実行は finally 部(クリーンアップ コードと呼ばれます)にジャンプします。 finally 部が実行された後、その例外ハンドラが呼び出されます。 例外が発生しない場合、クリーンアップ コードは通常の順序で実行されます。つまり、try ブロックにあるすべての文の後で実行されます。

メモリを割り当てた後でエラーが発生した場合にも割り当てたメモリが解放されるように finally ブロックを使用しているイベント ハンドラの例を次のコードで示します。

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;

finally ブロック内の文は、例外の発生に関係なく実行されます。 try 部の文で例外が発生しない場合は、finally ブロックが引き続き実行されます。

関連項目