异常:使用 MFC 宏和 C++ 异常

本文讨论编写同时使用 MFC 异常处理宏和 C++ 异常处理关键字书写代码的注意事项。

本文涵盖以下主题:

混合异常关键字和宏

可以在同一程序中混合 MFC 异常宏和 C++ 异常关键字。 但是,不能将 MFC 宏与同一块中的 C++ 异常关键字混合在一起,因为宏在超出范围时会自动删除异常对象,而使用异常处理关键字的代码则不会。 有关详细信息,请参阅文章异常:捕获和删除异常

宏和关键字之间的主要区别在于,当异常超出范围时,该宏会“自动”删除捕获的异常。 使用关键字的代码不会;catch 块中捕获的异常必须显式删除。 混合宏和 C++ 异常关键字可能会导致未删除异常对象时内存泄漏,或者在两次删除异常时堆损坏。

例如,以下代码使异常指针失效:

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_LAST 宏而不是 THROW 语句将导致“外部”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

有关详细信息,请参阅 异常:检查异常内容

另请参阅

异常处理