Recent

Author Topic: How to set exception mask for integer div-by-zero (EDivByZero) error?  (Read 4165 times)

dculp

  • Full Member
  • ***
  • Posts: 129
For floating point operations I can set an exception mask for division-by- zero as SetExceptionMask([exZeroDivide]); However, this doesn't work for integer div-by-zero (Show_exception(E) returns "Exception class: EDivByZero").

Is there a way to mask EDivByZero errors? (I suppose I could write a function Int_div that calls div within a "try .. except" block but a global integer mask would be better.)

Thanks,
Don C.

jamie

  • Hero Member
  • *****
  • Posts: 6801
Re: How to set exception mask for integer div-by-zero (EDivByZero) error?
« Reply #1 on: February 15, 2021, 10:56:13 pm »
Use a Try... Except .. .End block to catch it ?
The only true wisdom is knowing you know nothing

Kays

  • Hero Member
  • *****
  • Posts: 614
  • Whasup!?
    • KaiBurghardt.de
Re: How to set exception mask for integer div-by-zero (EDivByZero) error?
« Reply #2 on: February 16, 2021, 01:15:37 am »
Use a Try... Except .. .End block to catch it ?
Or, better, don’t let it happen in the first place. Ensure your divisor is non-zero. Exceptions are meant to signal something extraordinary, not a predictable condition.

[…] Is there a way to mask EDivByZero errors? […]
No, there is not, unless you’re programming your own OS.

On Linux you can install a signal handler that ignores the relevant signal, but this is just a terrible idea, because it’ll probably break lots of other things. You can also write your own errorProc, but simplest will be to just check for a zero divisor and you’re covered.
« Last Edit: February 16, 2021, 01:35:48 am by Kays »
Yours Sincerely
Kai Burghardt

Warfley

  • Hero Member
  • *****
  • Posts: 1865
Re: How to set exception mask for integer div-by-zero (EDivByZero) error?
« Reply #3 on: February 16, 2021, 01:39:36 am »
On Linux you can install a signal handler that ignores the relevant signal, but this is just a terrible idea, because it’ll probably break lots of other things.

This is a really bad idea as the behavior for ignoring SIGFPE is undefined. As the man page states:
Quote
Integer division by zero has
       undefined result.  On some architectures it will generate a
       SIGFPE signal.  (Also dividing the most negative integer by -1
       may generate SIGFPE.)  Ignoring this signal might lead to an
       endless loop.

winni

  • Hero Member
  • *****
  • Posts: 3197
Re: How to set exception mask for integer div-by-zero (EDivByZero) error?
« Reply #4 on: February 16, 2021, 01:44:41 am »
Hi!

The exception mask is only for floating point errors.

But  who is trying too fool me?????

An integer division by zero results in

E.message: Invalid floating point operation { !?!?!}
E.ClassName: EInvalidOp { Why not DivByZero?? }

IF a division by zero results in an floating point error, why can't I mask it by an Floating Point Exception????

There is not much logic in the terms. At least in the terms.

Winni

dculp

  • Full Member
  • ***
  • Posts: 129
Re: How to set exception mask for integer div-by-zero (EDivByZero) error?
« Reply #5 on: February 16, 2021, 05:17:23 am »
Use a Try... Except .. .End block to catch it ?
Or, better, don’t let it happen in the first place. Ensure your divisor is non-zero. Exceptions are meant to signal something extraordinary, not a predictable condition.

Then why are some FPU exceptions automatically masked while others (exZeroDivide) aren't? Why not have all exceptions unmasked and handled individually?

Running GetExceptionMask (using code from http://wiki.lazarus.freepascal.org/Multiplatform_Programming_Guide#Gtk2_and_masking_FPU_exceptions) gives --
   exInvalidOp - not masked!
   exDenormalized - masked!
   exZeroDivide - not masked!
   exOverflow - not masked!
   exUnderflow - masked!
   exPrecision - masked!

dculp

  • Full Member
  • ***
  • Posts: 129
Re: How to set exception mask for integer div-by-zero (EDivByZero) error?
« Reply #6 on: February 16, 2021, 05:37:25 am »
Hi!

The exception mask is only for floating point errors.

But  who is trying too fool me?????

An integer division by zero results in

E.message: Invalid floating point operation { !?!?!}
E.ClassName: EInvalidOp { Why not DivByZero?? }

IF a division by zero results in an floating point error, why can't I mask it by an Floating Point Exception????

There is not much logic in the terms. At least in the terms.

Winni

Interesting. When I test an integer division by zero I get --
   E.Message: Division by zero
   E.ClassName = EDivByZero
This occurs whether or not I have set any FPU masks.

However, I agree with your general sentiment.

Lazarus 2.0.2
Windows 7 Pro


PascalDragon

  • Hero Member
  • *****
  • Posts: 5858
  • Compiler Developer
Re: How to set exception mask for integer div-by-zero (EDivByZero) error?
« Reply #7 on: February 16, 2021, 09:02:22 am »
An integer division by zero results in

E.message: Invalid floating point operation { !?!?!}
E.ClassName: EInvalidOp { Why not DivByZero?? }

IF a division by zero results in an floating point error, why can't I mask it by an Floating Point Exception????

There is not much logic in the terms. At least in the terms.

Please show the code you used including which compiler version and what platform. For me the following code results in EZeroDivide for the floating point division and EDivByZero for the second on i386-win32 and x86_64-win64 with FPC 3.2.0.

Code: Pascal  [Select][+][-]
  1. program tdiv0;
  2.  
  3. {$mode objfpc}{$H+}
  4.  
  5. uses
  6.   SysUtils;
  7.  
  8. var
  9.   a, b: LongInt;
  10. begin
  11.   a := 1;
  12.   b := 0;
  13.   try
  14.     Writeln(a / b);
  15.   except
  16.     on e: Exception do
  17.       Writeln(e.ClassName, ' ', e.Message);
  18.   end;
  19.  
  20.   try
  21.     Writeln(a div b);
  22.   except
  23.     on e: Exception do
  24.       Writeln(e.ClassName, ' ', e.Message);
  25.   end;
  26. end.

Use a Try... Except .. .End block to catch it ?
Or, better, don’t let it happen in the first place. Ensure your divisor is non-zero. Exceptions are meant to signal something extraordinary, not a predictable condition.

Then why are some FPU exceptions automatically masked while others (exZeroDivide) aren't? Why not have all exceptions unmasked and handled individually?

Running GetExceptionMask (using code from http://wiki.lazarus.freepascal.org/Multiplatform_Programming_Guide#Gtk2_and_masking_FPU_exceptions) gives --
   exInvalidOp - not masked!
   exDenormalized - masked!
   exZeroDivide - not masked!
   exOverflow - not masked!
   exUnderflow - masked!
   exPrecision - masked!

The reason is Delphi-compatibility. Delphi has them masked the same and this way code ported from Delphi will meet the same behaviour.

And again: integer division is not handled by the FPU, thus it is not handled by the exception masks either, because these are only for FPU based operations.

dculp

  • Full Member
  • ***
  • Posts: 129
Re: How to set exception mask for integer div-by-zero (EDivByZero) error?
« Reply #8 on: February 16, 2021, 12:11:22 pm »
Quote
The reason is Delphi-compatibility. Delphi has them masked the same and this way code ported from Delphi will meet the same behaviour.

And again: integer division is not handled by the FPU, thus it is not handled by the exception masks either, because these are only for FPU based operations.

My point in showing default FPU masks was only to indicate that some math masks (regardless of FPU or integer) are on by default. Thus, someone originally must have felt that such masks weren't "exceptional".

Yes, ideally each operation should be checked to verify that it doesn't cause an exception. However, this isn't always practical. For example, if you're using someone else's package for which you either can't inspect the code or don't have time to inspect the code, then you may want to turn on a global mask such as for division by zero.
 

Mr.Madguy

  • Hero Member
  • *****
  • Posts: 864
Re: How to set exception mask for integer div-by-zero (EDivByZero) error?
« Reply #9 on: February 16, 2021, 12:14:42 pm »
Hi!

The exception mask is only for floating point errors.

But  who is trying too fool me?????

An integer division by zero results in

E.message: Invalid floating point operation { !?!?!}
E.ClassName: EInvalidOp { Why not DivByZero?? }

IF a division by zero results in an floating point error, why can't I mask it by an Floating Point Exception????

There is not much logic in the terms. At least in the terms.

Winni
What integer? Int64 on 32bit platform? It's implemented via FPU there.
Is it healthy for project not to have regular stable releases?
Just for fun: Code::Blocks, GCC 13 and DOS - is it possible?

nanobit

  • Full Member
  • ***
  • Posts: 168
Re: How to set exception mask for integer div-by-zero (EDivByZero) error?
« Reply #10 on: February 16, 2021, 12:19:45 pm »
The masking issue remind me of an old FPC bug  (issue #0036900).
If fp operations use SSE (not FPU), then masks are ignored:
translateMxcsr() ignores the exception mask.
Only unmasked exceptions should create pascal-exceptions.
It might be unrelated here though....

Kays

  • Hero Member
  • *****
  • Posts: 614
  • Whasup!?
    • KaiBurghardt.de
Re: How to set exception mask for integer div-by-zero (EDivByZero) error?
« Reply #11 on: February 16, 2021, 12:38:00 pm »
[…] The reason is Delphi-compatibility. […]
Ahh! “Our FPC developers on earth, hallowed be thy Delphi-compatibility, […]” ;)

Apart from that: The standards also (implicitly) dictate that.
  • A term of the form x / y shall be an error if y is zero; ignoring it would be [potentially] wrong.
  • Extended Pascal, ISO 10206, speaks of “reasonable approximations” regarding real arithmetics: Thus, #precision and #denormal can be masked without violating the standard. And it should be by default masked to produce a usable program. EP does not say such conditions shall emit errors, though, so it’s an “implementation” choice.
  • #underflow is masked, because EP specifically states arithmetics in the interval (-minReal, minReal) are not guaranteed to be correct [with the exception of zero]. Ergo, informing the programmer would be redundant/unfavorable, since he [presumably] already knows that from reading the standards.
And #overflow and #invalid are not masked, because that’s the Pascal spirit. Detect what’s detectable and report it. Favor an accurate program over a fast but potentially wrong program. Although, to be fair FPC has {$overFlowChecks} [for integer arithmetics] by default off. :( For “Delphi compatibility” I guess. %)
« Last Edit: February 16, 2021, 12:40:43 pm by Kays »
Yours Sincerely
Kai Burghardt

Warfley

  • Hero Member
  • *****
  • Posts: 1865
Re: How to set exception mask for integer div-by-zero (EDivByZero) error?
« Reply #12 on: February 16, 2021, 12:50:34 pm »
Yes, ideally each operation should be checked to verify that it doesn't cause an exception. However, this isn't always practical. For example, if you're using someone else's package for which you either can't inspect the code or don't have time to inspect the code, then you may want to turn on a global mask such as for division by zero.

No in this case you want to catch the exception on the callsite of that package function. Because if you just ignore the exception, the code continues as if it was a successfull operation, while the result of that operation is undefined. Your program is therefore in an undefined (potentially erroneous) state, and everything that is computed afterwards can not be guaranteed to be correct.

Thats why there are exceptions, they allow to catch errors on the callsite as they are propergated upwards until they are catched, and guarantee that no code that assumes the correctness of the previous behavior will be executed

PascalDragon

  • Hero Member
  • *****
  • Posts: 5858
  • Compiler Developer
Re: How to set exception mask for integer div-by-zero (EDivByZero) error?
« Reply #13 on: February 16, 2021, 12:58:02 pm »
Quote
The reason is Delphi-compatibility. Delphi has them masked the same and this way code ported from Delphi will meet the same behaviour.

And again: integer division is not handled by the FPU, thus it is not handled by the exception masks either, because these are only for FPU based operations.

My point in showing default FPU masks was only to indicate that some math masks (regardless of FPU or integer) are on by default. Thus, someone originally must have felt that such masks weren't "exceptional".

There is no "regardless of FPU or integer", the exception masks in unit Math are only for FPU exceptions. There is no mask for integer exceptions.

Also, as I said, the set of masked exceptions is due to Delphi compatibility.

[…] The reason is Delphi-compatibility. […]
Ahh! “Our FPC developers on earth, hallowed be thy Delphi-compatibility, […]” ;)

You can make fun of it all you want, fact is that the majority of the developers that come to FPC are those that had experience with Delphi (or sometimes TP) and thus this compatibility is important. Otherwise we'd have many more users complaining about (in this case) not receiving certain exceptions or receiving exceptions they didn't expect.

Although, to be fair FPC has {$overFlowChecks} [for integer arithmetics] by default off. :( For “Delphi compatibility” I guess. %)

Also due to performance. There would be more people complaining about the code being slower by default than there are people that are missing the checks.

lucamar

  • Hero Member
  • *****
  • Posts: 4219
Re: How to set exception mask for integer div-by-zero (EDivByZero) error?
« Reply #14 on: February 16, 2021, 01:00:53 pm »
No in this case you want to catch the exception on the callsite of that package function. [etc]

That's the problem: if the processor mask is set to ignore some error/exception the code can *not* raise it so there is nothing to catch even if you want to do so.
« Last Edit: February 16, 2021, 01:02:50 pm by lucamar »
Turbo Pascal 3 CP/M - Amstrad PCW 8256 (512 KB !!!) :P
Lazarus/FPC 2.0.8/3.0.4 & 2.0.12/3.2.0 - 32/64 bits on:
(K|L|X)Ubuntu 12..18, Windows XP, 7, 10 and various DOSes.

 

TinyPortal © 2005-2018