Monday, February 20, 2006

Catching Stack Overflow Exceptions, part 2

In a previous post, I reported that stack overflow exceptions can only be caught by structured exception handlers. We had a little internal discussion following this which I found interesting, I thought you might too.

Naveed explained that on Windows, it is possible to catch hardware exceptions with C++ exception handlers because Microsoft implemented C++ exceptions with SEH.

There are two routes to catching hardware exceptions:

  • Using catch(...)
  • Registering a structured exception handler to C++ translator function

As a bonus, he wrote a sample which demonstrates both of these techniques. His translator function converts SEH exceptions to unsigned ints, although you could build a custom C++ object and throw that instead.


// SEHInCppTest.cpp : Defines the entry point for the console application.
#include "stdafx.h"
#include
#include

void SehToUnsignedIntCppExceptionTranslator(unsigned int e, _EXCEPTION_POINTERS* p)
{
throw (unsigned int)e;
}

int _tmain(int argc, _TCHAR* argv[])
{
try {
__asm cli
} catch( ... ) {
printf("Caught: Privileged instruction.\n" );
}

try {
int* pInt=0;
*pInt = 10;
} catch( ... ) {
printf("Caught: Access violation.\n" );
}

try {
int dividend=1;
int divisor=0;
int quotient = dividend / divisor;
} catch( ... ) {
printf("Caught: Integer division by zero.\n" );
}

// requires compiler flag /EHa to use our translator function
_set_se_translator( SehToUnsignedIntCppExceptionTranslator );

try {
__asm cli
} catch( unsigned int e ) {
printf("Caught: SEH Exception Code (via translation) 0x%X.\n", e );
}

try {
int* pInt=0;
*pInt = 10;
} catch( unsigned int e ) {
printf("Caught: SEH Exception Code (via translation) 0x%X.\n", e );
}

try {
int dividend=1;
int divisor=0;
int quotient = dividend / divisor;
} catch( unsigned int e ) {
printf("Caught: SEH Exception Code (via translation) 0x%X.\n", e );
}

return 0;
}

1 comment:

This-Statement-Is-False said...

Hey, wow, that's really neat. Now my applications can handle Runtime Exceptions (not that my code is usually poorly written enough to encounter them often).

I have a lower level question about try-catch blocks.

How are these things handled on the stack? I know it might be compiler-dependent, but... what I am thinking is that try clauses have their own stack frame with a magic value and a pointer(s) to relevant catch clauses. During stack unwinding after an exception is raised, code looks for the magic value to find try clauses, then iterates though the catch clauses for a relevant handler?

That's just a guess...

Please, if you know, email me at normlegaia@gmail.com.