C++ Exception Handling

C++ Exception Handling

Quick quiz: What is the behavior of the following code:

#include <stdio.h>

int main(int argc, char* argv[])
{
    try
    {
        *((char*) 0) = 1;
    }
    catch (...)
    {
        printf("Caught exception.\n");
    }

    return 0;
}

Surprisingly, it depends! As I would expect, on many operating system / compiler combinations (such as gcc version 3.4.4 20050721 (Red Hat 3.4.4-2) as tested by Keith Garner), the dereference of the null pointer leads to a segmentation fault. However, both Microsoft Visual Studio 6.0 and Visual Studio .NET 2003 print the message Caught exception. and exit gracefully. Strange!

This behavior appears to be an unintended consequence of the way C++ exceptions were implemented by Microsoft. Seemingly, Visual C++ implements the C++ exception handling mechanism using Structured Exception Handling (SEH), and the null pointer dereference leads to a Structured Exception, most likely an EXCEPTION_ACCESS_VIOLATION. (For a list of possible SEH codes, see the documentation for the GetExceptionCode() function.) The catch (...) statement ends up catching the Structured Exception, and the code proceeds accordingly.

This means that in Visual C++ 6.0 and Visual C++ .NET 2003, catch (...) does not catch only exceptions thrown using the C++ throw keyword; rather, it may also catch any number of Structured Exceptions, including division by 0, stack overflow, data misalignment, etc. Fortunately, it seems that this behavior may be disabled with the /EHs compiler option in Visual C++ .NET 2005.

However, until the day comes when all Windows code is compiled with Visual C++ .NET 2005 and the /EHs option, I suggest avoiding the catch (...) construct altogether. Personally, I’ve chosen to inherit my custom-defined exceptions from STL’s std::exception and use catch (const std::exception& ex) instead.