1) catching the exception will work (as you observed). However, you will break the exception handler chaining if you do not place the exception registration record on the stack. That might lead to some odd effects (remember there is a default exception handler that the OS installs in order to catch exceptions in your program).
2) As far as I can tell from your code, the only reason that you need to catch exceptions is so that you can reset the FPU controls flags to turn back off FP exceptions. I am no C++ expert. I see these solutions (from best to worst)
a) have a look at C++ exceptions. I would hope that they allow to catch HW exceptions. But I don't know how you would be able to continue program execution from the point of exception
b) write C macros to set up and remove exception handlers. This is how XWorkplace does it and it works just fine. In the following example, for your case, you will not need to use setjmp/longjmp because you can always continue execution from the point of exception:
typedef struct _EXCEPTIONREGISTRATIONRECORD2
{
EXCEPTIONREGISTRATIONRECORD reg;
jmp_buf jmp;
} EXCEPTIONREGISTRATIONRECORD2, *PEXCEPTIONREGISTRATIONRECORD2;
extern ULONG APIENTRY ExceptionHandler(
PEXCEPTIONREPORTRECORD pRep,
PEXCEPTIONREGISTRATIONRECORD2 pReg,
PCONTEXTRECORD pCtx,
PVOID pDispCtx);
#define TRY(except) \
{ \
EXCEPTIONREGISTRATIONRECORD2 except={0}; \
except.reg.ExceptionHandler = (ERR)ExceptionHandler; \
DosSetExceptionHandler((PEXCEPTIONREGISTRATIONRECORD)&except); \
if (setjmp(except.jmp) == 0) {
#define CATCH() \
} else {
#define ENDTRY(except) \
} \
DosUnsetExceptionHandler((PEXCEPTIONREGISTRATIONRECORD)&except); \
}
...
ULONG APIENTRY ExceptionHandler(
PEXCEPTIONREPORTRECORD pRep,
PEXCEPTIONREGISTRATIONRECORD2 pReg,
PCONTEXTRECORD pCtx,
PVOID pDispCtx)
{
if (pRep->fHandlerFlags & (EH_EXIT_UNWIND|EH_UNWINDING|EH_NESTED_CALL))
{
return XCPT_CONTINUE_SEARCH;
}
switch (pRep->ExceptionNum)
{
case XCPT_ACCESS_VIOLATION:
case XCPT_ILLEGAL_INSTRUCTION:
case XCPT_PRIVILEGED_INSTRUCTION:
case XCPT_INVALID_LOCK_SEQUENCE:
case XCPT_INTEGER_DIVIDE_BY_ZERO:
case XCPT_INTEGER_OVERFLOW:
case XCPT_FLOAT_DIVIDE_BY_ZERO:
case XCPT_FLOAT_OVERFLOW:
case XCPT_FLOAT_UNDERFLOW:
case XCPT_FLOAT_INVALID_OPERATION:
case XCPT_FLOAT_DENORMAL_OPERAND:
case XCPT_FLOAT_INEXACT_RESULT:
case XCPT_FLOAT_STACK_CHECK:
longjmp(pReg->jmp,1);
default:
break;
}
return XCPT_CONTINUE_SEARCH;
}
c) allocate an exception registration record on the stack and pass the address to your constructor. In the constructor, register the handler and save the address of the exception registration record to a private variable. Then, in the destructor use that address to deregister the exception handler.
Lars