Share via


Exceptions: Using MFC Macros and C++ Exceptions

OverviewHow Do IFAQ

This article discusses considerations for writing code that uses both the MFC exception-handling macros and the C++ exception-handling keywords.

This article covers the following topics:

  • Mixing exception keywords and macros

  • Try blocks inside catch blocks

Mixing Exception Keywords and Macros

You can mix MFC exception macros and C++ exception keywords in the same program. But you cannot mix MFC macros with C++ exception keywords in the same block because the macros delete exception objects automatically when they go out of scope, whereas code using the exception-handling keywords does not. For more information, see the article Exceptions: Catching and Deleting Exceptions.

The main difference between the macros and the keywords is that the macros “automatically” delete a caught exception when the exception goes out of scope. Code using the keywords does not; exceptions caught in a catch block must be explicitly deleted. Mixing macros and C++ exception keywords can cause memory leaks when an exception object is not deleted, or heap corruption when an exception is deleted twice.

The following code, for example, invalidates the exception pointer:

TRY
{
    TRY
    {
        // Do something to throw an exception.
    }
    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

The problem occurs because e is deleted when execution passes out of the “inner” CATCH block. Using the THROW_LAST macro instead of the THROW statement will cause the “outer” CATCH block to receive a valid pointer:

TRY
{
    TRY
    {
        // Do something to throw an exception.
    }
    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

Try Blocks Inside Catch Blocks

You cannot re-throw the current exception from within a try block that is inside a CATCH block. The following example is invalid:

TRY
{
    // Do something to throw an exception.
}
CATCH(CException, e)
{
    try
    {
        throw;  // Wrong.  Causes e (the exception
                // being thrown) to be deleted.
    }
    catch(CException exception)
    {
    }
}
END_CATCH

For related information, see Exceptions: Examining Exception Contents.