標準例外と構造化例外の混在(C++)
Win32 の構造化例外(C++) への移動
C++ プログラムで構造化例外を使用する場合は、いくつかの問題点をわかっている必要があります。まず、C++Builder では C++ 例外と Win32 構造化例外を実装していますが、C++ 例外は __except ブロックに対して透過的です。
try ブロックの後に記述できるのは、ちょうど 1 つの except ブロックか少なくとも 1 つの catch ブロックのどちらかです。この両者を混在させようとすると、コンパイラ エラーが発生します。両方のタイプの例外を処理する必要があるコードは、以下のように、2 つの try ブロックの中にネストさせなければなりません。
try {
EXCEPTION_POINTERS *xp;
try {
func();
}
__except (xfilter(xp = GetExceptionInformation())) {
// ...
}
}
catch (...) {
// ...
}
関数の throw() 仕様は、Win32 例外に関しては、プログラムの動作に影響を与えません。さらに、terminate() を呼び出す C++ プログラムとは異なり、未処理の例外は最終的にオペレーティング システムで処理されます(デバッガが最初にそれを処理しない場合)。
-xd
コンパイラ オプション(デフォルトではオン)を付けてコンパイルされたモジュールはどれも、auto 記憶クラス指定子の付いたすべてのオブジェクトのデストラクタを呼び出します。スタックの巻き戻しは、例外が送出された位置から、例外が捕捉された位置まで行われます。
C++ プログラムにおける C ベースの例外の例
/* Program results:
Another exception:
Caught a C-based exception.
Caught C++ exception: Hardware error: Divide by 0 :
C++ allows __finally too!
*/
#include <stdio.h>
#include <string.h>
#include <windows.h>
class Exception {
public:
Exception(char* s = "Unknown") {
what = strdup(s);
}
Exception(const Exception& e) {
what = strdup(e.what);
}
~Exception() {
delete[]what;
}
char* msg() const {
return what;
}
private:
char* what;
};
int main() {
float e, f, g;
try {
try {
f = 1.0;
g = 0.0;
try {
puts("Another exception:");
e = f / g;
}
__except (EXCEPTION_EXECUTE_HANDLER) {
puts("Caught a C-based exception.");
throw(Exception("Hardware error: Divide by 0"));
}
}
catch (const Exception& e) {
printf("Caught C++ Exception: %s :\n", e.msg());
}
}
__finally {
puts("C++ allows __finally too!");
}
return e;
}