Problem with handling division by zero exception
This may not be the right group, so if you know of a better one, please
direct me to it.
The code below (I'm showing just the relevant parts, no class definitions)
is intended to turn division by 0 (DBZ) structured exception into C++
exceptions, and it works almost well.
The way it works: first I call install which sets my_translator as the
structured exception handler, then when the DBZ happens, I re-throw it as a
C++ DivideByZeroExceptionImpl.
Note the calls to _controlfp in install to enable DBZ error in the FPU and
_clearfp to clear the exception after it was caught.
The only problem I have with this is that starting after the first 5 or so
such exceptions, after each C++ exception is caught, the first division
operation, no matter where in the code or what the operands, will result in
a NaN (Not a number) result. So to avoid this, I first perform a dummy
division then I continue the code normally. My understanding was that the
call to _clearfp would take care of any such problem.
All this is done using Visual Studio .Net 2003, and all the compiler options
that have to do with this are set properly (/EHa).
Any idea why this is happening and how to avoid it?
Related to this, I am puzzled by two other issues:
- why isn't it floating point DBZ exception enabled by default? IMO it is a
runtime error almost as serious as an access violation that must be handled
in most cases.
- why isn't a std::runtime_error exception thrown in case of a DBZ error?
Can this be enabled?
////////////////////////////////
void my_translator(unsigned code, EXCEPTION_POINTERS *info)
{
switch ( code )
{
case EXCEPTION_INT_DIVIDE_BY_ZERO:
case EXCEPTION_FLT_DIVIDE_BY_ZERO:
{
_clearfp();
}
throw DivideByZeroExceptionImpl(*info);
break;
default:
throw StructuredException( UNKNOWN_STRUCTURED_ERROR, *info);
break;
}
}
void StructuredException::install() throw()
{
int _cw;
_cw = _controlfp( 0,0 );
// Set the exception masks OFF, turn exceptions on.
int cwx = _cw & ~(EM_ZERODIVIDE);
// Set the control word.
_controlfp( cwx, MCW_EM );
_set_se_translator( my_translator );
}
// C++ DBZ exception handler
try
{
....
}
catch( const DivideByZeroException& e )
{
// dummy division
double xxx = 5/10;
// continue the handler
}
//////////////////////////////////////
Thanks,
a