例外処理 : MFC マクロと C++ 例外機構の使用

この記事では、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 マクロを使用すると、"外側の" 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 ブロック内の try ブロック

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

詳細については、「例外処理: 例外の内容の調査」を参照してください。

関連項目

例外処理