SEH 終了処理ブロック(C++)
Win32 の構造化例外(C++) への移動
構造化例外処理モデルでは、ガード ブロックが正常に終了した場合にも例外が発生した場合にも実行される "終了処理ブロック" をサポートしています。C++Builder コンパイラでは、次の構文によって C でこれをサポートしています。
__try {
func();
}
__finally {
// this happens whether func() raises an exception or not
}
終了処理ブロックは C++ 拡張でサポートされていて、クリーンアップの処理を __finally ブロックで行うことができます。
try {
func();
}
__finally {
// this happens whether func() raises an exception or not
}
次に終了処理ブロックの例を示します。
/* Program results:
An exception:
Caught an exception.
The __finally is executed too!
No exception:
No exception happened, but __finally still executes!
*/
#include <stdio.h>
#include <windows.h>
int main() {
float e, f, g;
try {
f = 1.0;
g = 0.0;
try {
puts("An exception:");
e = f / g;
}
__except (EXCEPTION_EXECUTE_HANDLER) {
puts("Caught an exception.");
}
}
__finally {
puts("The __finally is executed too!");
}
try {
f = 1.0;
g = 2.0;
try {
puts("No exception:");
e = f / g;
}
__except (EXCEPTION_EXECUTE_HANDLER) {
puts("Caught an exception.");
}
}
__finally {
puts("No exception happened, but __finally still executes!");
}
return e;
}
C++ コードでは、スコープが終了したときに呼び出されるデストラクタを持つローカル オブジェクトを作成することで、"終了処理ブロック" を処理することもできます。C++Builder の構造化例外ではデストラクタによるクリーンアップをサポートしているため、この方法は発生した例外の型に関係なく有効です。
メモ: 例外が発生してプログラムで処理されなかった場合にどうなるかに関する 1 つの特別な状況があります。C++ 例外の場合、C++Builder コンパイラはローカル オブジェクトのデストラクタを呼び出します(この呼び出しは言語定義で要求されてはいません)。それに対して、未処理の Win32 例外では、デストラクタによるクリーンアップは行われません。
メモ: 標準の C++ では
finally
ブロックをサポートしていません。その代わりに、デストラクタを使用してリソースの解放を行うのが一般的です。ただし、Delphi で書かれている VCL を使用する場合、VCL オブジェクトはヒープ上に割り当てなければならないため、finally
ブロックが重要なツールになります。