Mixing C++ and SEH exception handling

The RaiseException Windows function will throw an SEH exception. The first parameter is the exception code and the second indicates if the process can continue after this exception is handled (0 means it can). The third and fourth parameters give additional information about the exception. The fourth parameter is a pointer to an array with these additional parameters and the number of parameters is given in the third parameter.

With /EHa, you can write code like this:

    try  
{
RaiseException(1, 0, 0, nullptr);
}
// legal code, but don't do it
catch(...)
{
cout << "SEH or C++ exception caught" << endl;
}

The problem with this code is that it handles all SEH exceptions. This is quite dangerous because some SEH exceptions may indicate that the process state is corrupted, so it is dangerous for the process to continue. The C Runtime Library provides a function called _set_se_translator that provides a mechanism to indicate which SEH exceptions are handled by try. This function is passed a pointer by a function that you write with this prototype:

    void func(unsigned int, EXCEPTION_POINTERS*);

The first parameter is the exception code (which will be returned from the GetExceptionCode function) and the second parameter is the return from the GetExceptionInformation function and has any additional parameters associated with the exception (for example, those passed through the third and fourth parameters in RaiseException). You can use these values to throw a C++ exception in place of the SEH. If you provide this function:

    void seh_to_cpp(unsigned int code, EXCEPTION_POINTERS*) 
{
if (code == 1) throw exception("my error");
}

You can now register the function before handling an SEH exception:

    _set_se_translator(seh_to_cpp); 
try
{
RaiseException(1, 0, 0, nullptr);
}
catch(exception& e)
{
cout << e.what() << endl;
}

In this code, the RaiseException function is raising a custom SEH with a value of 1. This translation is perhaps not the most useful, but it illustrates the point. The winnt.h header file defines the exception code for the standard SEH exceptions that can be raised in Windows code. A more useful translation function would be:

    double reciprocal(double d) 
{
return 1.0 / d;
}

void seh_to_cpp(unsigned int code, EXCEPTION_POINTERS*)
{
if (STATUS_FLOAT_DIVIDE_BY_ZERO == code ||
STATUS_INTEGER_DIVIDE_BY_ZERO == code)
{
throw invalid_argument("divide by zero");
}
}

This allows you to call the reciprocal function as following:

    _set_se_translator(seh_to_cpp); 
try
{
reciprocal(0.0);
}
catch(invalid_argument& e)
{
cout << e.what() << endl;
}
..................Content has been hidden....................

You can't read the all page of ebook, please click here login for view all page.
Reset