The sad history of the MFC TRY/CATCH macros

Raymond Chen


Why does MFC define TRY/CATCH macros? Why can’t it use standard C++ exception handling?

This is another case of asking why they didn’t use the Space Shuttle to rescue Apollo 13.

MFC was first released in 1992. At that time, C++ was a cool new programming language that everybody was interested in. Back in the early days, there were no templates, there was no standard library, no placement new, no namespaces, and no exceptions.¹

That meant that the MFC team had to invent their own exceptions, which they did with macros like TRY and CATCH. These macros were deprecated in MFC 3.0 (released in 1994), but for compatibility the macros continue to exist so that pre-MFC-3.0 code remains source-level compatible. The macros now just do standard C++ try and catch operations, although there’s a _AFX_OLD_EXCEPTIONS symbol you can define to make them revert to the old setjmp-based fake exception handling, for binary compatibility.

MSDN has a guide to converting from MFC exceptions to C++ exceptions. So convert your code already. You’ve had 25 years.

¹ This implies that a failed new didn’t throw a std::bad_alloc exception, seeing as neither namespaces nor exceptions existed yet! Instead, a failed new simply returned NULL

² The nullptr keyword wouldn’t exist for nearly 20 years.


Comments are closed.

  • Avatar
    Pierre Baillargeon

    As for new returning null, I had to support this for a while, but by that time placement new existed. So what I did was define a not_null_t with a static instance called not_null and created a placement-new version taking a not_null_t which enforced that failure would throw an exception. You would do:
        my_struct* ps = new(not_null) my_struct;

  • Avatar

    “So convert your code already. You’ve had 25 years.” Well, the documentation says, “You probably do not need to convert existing code.” So that’s an excellent justification doing nothing.