What is the difference between try/catch and MFC TRY/CATCH?

Viewed 699

I am refactoring some legacy C++ MFC code and have come across this construct:

TRY
{
    // do some stuff
}
CATCH
{
    // do some other stuff
}
END_CATCH

To me this seems quite unusual, and I am trying to understand what is the benefit of using TRY/CATCH in favor of try/catch.

I see that TRY creates an instance of AFX_EXCEPTION_LINK and I don't quite understand the purpose of this. My googling skill failed miserably.

1 Answers

MFC (and its exception processing macros) predate the C++98 language specification. The macros attempt to abstract common boilerplate code away, when using exceptions in MFC. The boilerplate code is necessary due to the design decision, that exceptions in MFC are dynamically allocated1, and need to be manually disposed.

The steps required to replace the MFC exception handling macros with C++ exception handling are documented under Exceptions: Converting from MFC Exception Macros:

To convert code using macros to use the C++ exception-handling keywords

  1. Locate all occurrences of the MFC macros TRY, CATCH, AND_CATCH, END_CATCH, THROW, and THROW_LAST.

  2. Replace or delete all occurrences of the following macros:

    • TRY (Replace it with try)
    • CATCH (Replace it with catch)
    • AND_CATCH (Replace it with catch)
    • END_CATCH (Delete it)
    • THROW (Replace it with throw)
    • THROW_LAST (Replace it with throw)
  3. Modify the macro arguments so that they form valid exception declarations.

    For example, change

    CATCH(CException, e)
    

    to

    catch(CException* e)
    
  4. Modify the code in the catch blocks so that it deletes exception objects as necessary. For more information, see the article Exceptions: Catching and Deleting Exceptions.

Here is an example of exception-handling code using MFC exception macros. Note that because the code in the following example uses the macros, the exception e is deleted automatically:

TRY
{
   // Do something to throw an exception.
   AfxThrowUserException();
}
CATCH(CException, e)
{
   if (m_bPassExceptionsUp)
      THROW_LAST();
   if (m_bReturnFromThisFunction)
      return;
   // Not necessary to delete the exception e.
}
END_CATCH

The code in the next example uses the C++ exception keywords, so the exception must be explicitly deleted:

try
{
   // Do something to throw an exception.
   AfxThrowUserException();
}
catch(CException* e)
{
   if (m_bPassExceptionsUp)
      throw;
   if (m_bThrowDifferentException)
   {
      e->Delete();
      throw new CMyOtherException;
   }
   if (m_bReturnFromThisFunction)
   {
      e->Delete();
      return;
   }
   e->Delete();
}

The conversion is almost mechanical, as long as you remember to manually delete MFC exceptions by invoking CException::Delete.


1 This is in contrast to the C++ exception handling convention today: Throw by value, catch by (const) reference.

Related