Am 22.08.2012 13:47, schrieb OBones:
Jonas Maebe wrote:

OBones wrote on Wed, 22 Aug 2012:

Olivier SANNIER wrote:
Does any of you have any suggestion as to explain this behavior, and
best of
all, how to fix it?
I went further and changed the code this so that I can get better
details as to where the exception is coming from:

EControlC is the translation of run time error 217. The Win32
exception handler also sets error code 217 in case of an unknown
exception  (the Win64 exception handler does the same, for that
matter). Apparently Win32 is not reporting that division-by-zero as
either STATUS_INTEGER_DIVIDE_BY_ZERO or STATUS_FLOAT_DIVIDE_BY_ZERO,
while Win64 does do this.

You can try debugging syswin32_i386_exception_handler in
rtl/win32/system.pp to see what exception Win32 reports instead.
Thanks for the confirmation as I was heading that way when I posted the
message, without much hope.
But now that I have put that idea to full length, it became clear that
the problem is not (entirely) with Win32 but because the exception
handler does not handle the STATUS_FLOAT_MULTIPLE_FAULTS and
STATUS_FLOAT_MULTIPLE_TRAPS cases.
And as you said, when it does not know what to do, it gives 217 that
gets later translated to Control C, which to me is a bit misleading. I'd
rather have a 202, External Exception.
Anyway, I installed my own exception handler using
SetUnhandledExceptionFilter, saving the return value and I wrote my own
"overloaded" version of the exception handler that does this:

function GetMXCSR: Cardinal;
asm
   stmxcsr Result
end;

function MyUnhandledExceptionFilter(excep : PExceptionPointers) :
Longint;stdcall;
const
   MXCSR_IE = $01;   // invalid operation
   MXCSR_DE = $02;   // denormal
   MXCSR_ZE = $04;   // divide by zero
   MXCSR_OE = $08;   // overflow
   MXCSR_UE = $10;   // underflow
   MXCSR_PE = $20;   // precision
var
   MXCSR: Cardinal;
begin
   WriteLn('MyUnhandledExceptionFilter: ' + IntToHex(GetMXCSR, 2));
   WriteLn(IntToHex(excep^.ExceptionRecord^.ExceptionCode, 8));
   WriteLn(IntToHex(EXCEPTION_FLT_DIVIDE_BY_ZERO, 8));
   if Assigned(PreviousUnhandledExceptionFilter) then
   begin
     if (excep^.ExceptionRecord^.ExceptionCode =
STATUS_FLOAT_MULTIPLE_FAULTS) or
       (excep^.ExceptionRecord^.ExceptionCode =
STATUS_FLOAT_MULTIPLE_TRAPS) then
     begin
       MXCSR := GetMXCSR;

       if MXCSR and MXCSR_IE = MXCSR_IE then
         excep^.ExceptionRecord^.ExceptionCode :=
STATUS_FLOAT_INVALID_OPERATION
       else if MXCSR and MXCSR_DE = MXCSR_DE then
         excep^.ExceptionRecord^.ExceptionCode :=
STATUS_FLOAT_DENORMAL_OPERAND
       else if MXCSR and MXCSR_ZE = MXCSR_ZE then
         excep^.ExceptionRecord^.ExceptionCode :=
STATUS_FLOAT_DIVIDE_BY_ZERO
       else if MXCSR and MXCSR_OE = MXCSR_OE then
         excep^.ExceptionRecord^.ExceptionCode := STATUS_FLOAT_OVERFLOW
       else if MXCSR and MXCSR_UE = MXCSR_UE then
         excep^.ExceptionRecord^.ExceptionCode := STATUS_FLOAT_UNDERFLOW
       else if MXCSR and MXCSR_PE = MXCSR_PE then
         excep^.ExceptionRecord^.ExceptionCode :=
STATUS_FLOAT_INEXACT_RESULT;
     end;

     Result := PreviousUnhandledExceptionFilter(excep);
   end;
end;

I know that I hide the case where there might be two errors at once, but
strangely enough, the MXCSR register only contained one exception bit
set in my case, so I don't understand why Win32 is giving a "multiple
traps" error.

So right, now, using this I'm getting the appropriate exception, I'm
just left wondering if this code (or a similar one) should be added to
FreePascal so that other people are not having the same issue as I'm
having.

Note to others: this is only ever useful in Win32 because Win64 does not
use the handlers set by SetUnhandledExceptionFilter

Win64 (and Win32 systems after Windows XP) do all use SetUnhandledExceptionFilter, but we do use AddVectoredExceptionHandler on Win64 (at least if not compiled using the new Win64 SEH code in 2.7.1 ;) ) of which the handlers are called before the handler set by SetUnhandledExceptionFilter is called.

Regards,
Sven

_______________________________________________
fpc-pascal maillist  -  fpc-pascal@lists.freepascal.org
http://lists.freepascal.org/mailman/listinfo/fpc-pascal

Reply via email to