この記事では、MFC 例外処理マクロと C++ 例外処理キーワードの両方を使用するコードを記述する際の考慮事項について説明します。
この記事では、次のトピックについて説明します。
例外キーワードとマクロの混在
MFC 例外マクロと C++ 例外キーワードを同じプログラムに混在させることができます。 ただし、MFC マクロと同じブロック内の C++ 例外キーワードを混在させることはできません。例外処理キーワードを使用するコードでは例外オブジェクトがスコープ外になると例外オブジェクトが自動的に削除されるためです。 詳細については、「 例外: 例外のキャッチと削除」を参照してください。
マクロとキーワードの主な違いは、例外がスコープ外になったときにキャッチされた例外をマクロが "自動的に" 削除することです。 キーワードを使用するコードは使用しません。catch ブロックでキャッチされた例外は明示的に削除する必要があります。 マクロと C++ 例外キーワードを混在させると、例外オブジェクトが削除されない場合にメモリ リークが発生したり、例外が 2 回削除されたときにヒープが破損したりする可能性があります。
たとえば、次のコードは例外ポインターを無効にします。
TRY
{
TRY
{
// Do something to throw an exception.
AfxThrowUserException();
}
CATCH(CException, e) // The "inner" catch block
{
throw; // Invalid attempt to throw exception
// to the outer catch block below.
}
END_CATCH
}
CATCH(CException, e) // The "outer" catch block
{
// Pointer e is invalid because
// it was deleted in the inner catch block.
}
END_CATCH
この問題は、実行が "内部" CATCH ブロックから渡されたときにe
が削除されるために発生します。
THROW ステートメントの代わりに THROW_LAST マクロを使用すると、"outer" CATCH ブロックは有効なポインターを受け取ります。
TRY
{
TRY
{
// Do something to throw an exception.
AfxThrowUserException();
}
CATCH(CException, e) // The "inner" catch block
{
THROW_LAST(); // Throw exception to the outer catch block below.
}
END_CATCH
}
CATCH(CException, e) // The "outer" catch block
{
// Pointer e is valid because
// THROW_LAST() was used.
}
END_CATCH
Catch ブロック内のブロックを試す
CATCH ブロック内の try
ブロック内から現在の例外を再スローすることはできません。 次の例は無効です。
TRY
{
// Do something to throw an exception.
AfxThrowUserException();
}
CATCH(CException, e)
{
try
{
throw; // Wrong. Causes e (the exception
// being thrown) to be deleted.
}
catch (CException* exception)
{
exception->ReportError();
}
}
END_CATCH
詳細については、「 例外: 例外の内容を調べる」を参照してください。