How to set exception mask for integer div-by-zero (EDivByZero) error? lazarus / 21-General ---------------------------------------------------------------------- dculp · 2021-02-15 16:15 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 · 2021-02-15 21:56 Use a Try... Except .. .End block to catch it ? ---------------------------------------------------------------------- Kays · 2021-02-16 00:15 Quote from: jamie on February 15, 2021, 10:56:13 pmUse 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. Quote from: dculp on February 15, 2021, 05:15:33 pm[…] 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. ---------------------------------------------------------------------- Warfley · 2021-02-16 00:39 Quote from: Kays on February 16, 2021, 01:15:37 amOn 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 · 2021-02-16 00:44 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 · 2021-02-16 04:17 Quote from: Kays on February 16, 2021, 01:15:37 amQuote from: jamie on February 15, 2021, 10:56:13 pmUse 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.freepasc al.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 · 2021-02-16 04:37 Quote from: winni on February 16, 2021, 01:44:41 amHi! 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 · 2021-02-16 08:02 Quote from: winni on February 16, 2021, 01:44:41 amAn 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][+][-]window.onload = function(){var x1 = document.getElementById("main_content_section"); if (x1) { var x = document.getElementsByClassName("geshi");for (var i = 0; i program tdiv0; {$mode objfpc}{$H+} uses  SysUtils; var  a, b: LongInt;begin  a := 1;  b := 0;  try    Writeln(a / b);  except    on e: Exception do    Writeln(e.ClassName, ' ', e.Message);  end;   try    Writeln(a div b);  except    on e: Exception do      Writeln(e.ClassName, ' ', e.Message);  end;end. Quote from: dculp on February 16, 2021, 05:17:23 amQuote from: Kays on February 16, 2021, 01:15:37 amQuote from: jamie on February 15, 2021, 10:56:13 pmUse 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.freepasc al.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 · 2021-02-16 11:11 QuoteThe 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 · 2021-02-16 11:14 Quote from: winni on February 16, 2021, 01:44:41 amHi! 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. ---------------------------------------------------------------------- nanobit · 2021-02-16 11:19 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 · 2021-02-16 11:38 Quote from: PascalDragon on February 16, 2021, 09:02:22 am[…] 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. ---------------------------------------------------------------------- Warfley · 2021-02-16 11:50 Quote from: dculp on February 16, 2021, 12:11:22 pmYes, 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 · 2021-02-16 11:58 Quote from: dculp on February 16, 2021, 12:11:22 pmQuoteThe 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. Quote from: Kays on February 16, 2021, 12:38:00 pmQuote from: PascalDragon on February 16, 2021, 09:02:22 am[…] 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. Quote from: Kays on February 16, 2021, 12:38:00 pmAlthough, 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 · 2021-02-16 12:00 Quote from: Warfley on February 16, 2021, 12:50:34 pmNo 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. ---------------------------------------------------------------------- dculp · 2021-02-16 12:51 Quote from: Warfley on February 16, 2021, 12:50:34 pmQuote from: dculp on February 16, 2021, 12:11:22 pmYes, 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 I don't understand. Assume that the package doesn't mask a particular exception and that I also don't mask this exception. Also assume that that exception isn't properly handled locally (e.g., by a try..except or some other method), then wouldn't the program crash immediately -- i.e., how would the exception be propagated upward so that I could catch it? (This would also apply to my own code if I didn't handle an exception locally -- which is very possible since I have a lot of very old code.) ---------------------------------------------------------------------- Warfley · 2021-02-16 12:57 Quote from: lucamar on February 16, 2021, 01:00:53 pmThat'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. The point what I was trying to make is that such a mask does not make any sense. There are 3 cases when the mask is set: 1. There is a division but the divisor is never 0. In that case the mask doesn't matter 2. There is a division where the divisor can be 0 and the result is used. In that case you can work on undefined data, meaning the correctness of your code is not guaranteed, or in other words, your code is broken 3. there is a division where the divisor can be 0 but the result is never touched. In that case you avoid the exception without getting into undefined behavior, but in that case you could simply not perform that division. Under the assumption that your goal is to write correct code, I don't see any usecase for the ability to mask out such an exception. There are usecases for deactivating exceptions for unexpected but defined events. E.g. if you deactivate divide by 0 exception for pythons numpy float type, dividing by 0 will result in +/- infinity. While this is mathematically a little bit wonky, it is well defined and can be quite useful at times. But allowing *undefined* behavior is by definition broken code, and personally I think that it is good language design to allow for a feature that only benefits the creation of broken code Quote from: dculp on February 16, 2021, 01:51:11 pmI don't understand. Assume that the package doesn't mask a particular exception and that I also don't mask this exception. Also assume that that exception isn't properly handled locally (e.g., by a try..except or some other method), then wouldn't the program crash immediately -- i.e., how would the exception be propagated upward so that I could catch it? (This would also apply to my own code if I didn't handle an exception locally -- which is very possible since I have a lot of very old code.) Yes, but the program crashing is better then the program being in an undefined state. In an undefined state everything the program does is potentially erroneous and no result and behavior can be trusted from that point onwards. A program thats crashed can at least not do anything wrong. Let's assume the program has some task management functionality and the result of that operation is used to determine if a process should be killed. The undefined behavior might lead to killing a system process that results in a total shutdown. What is better, the application crashing or the whole system crashing? Erroneous computations could lead to simply wrong results, faulty logic or even corrupt other data, which can destroy data in the long term. If an error is not properly handled, shutting down the whole program is the most sensible approach ---------------------------------------------------------------------- winni · 2021-02-16 16:02 Quote from: dculp on February 16, 2021, 05:37:25 amQuote from: winni on February 16, 2021, 01:44:41 amHi! 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 Strange, strange!!! I use Code: Pascal  [Select][+][-]window.onload = function(){var x1 = document.getElementById("main_content_section"); if (x1) { var x = document.getElementsByClassName("geshi");for (var i = 0; i var i : Integer = 0;begin   try  showMessage (IntToStr(10 div i));  except  on E:  Exception do showMessage (E.Message+LineEnding+E.ClassName); end; end;                   results - as I told above - in E.message: Invalid floating point operation { !?!?!} E.ClassName: EInvalidOp { Why not DivByZero?? } Winni ---------------------------------------------------------------------- PascalDragon · 2021-02-17 08:30 Quote from: winni on February 16, 2021, 05:02:57 pmStrange, strange!!! I use Code: Pascal  [Select][+][-]window.onload = function(){var x1 = document.getElementById("main_content_section"); if (x1) { var x = document.getElementsByClassName("geshi");for (var i = 0; i var i : Integer = 0;begin   try  showMessage (IntToStr(10 div i));  except  on E:  Exception do showMessage (E.Message+LineEnding+E.ClassName); end; end;                   results - as I told above - in E.message: Invalid floating point operation { !?!?!} E.ClassName: EInvalidOp { Why not DivByZero?? } Again, please provide a full, compilable example and not simply a snippet. The code I posted here works correctly for example. Also you did not mention your FPC version or the used target. ---------------------------------------------------------------------- AlexTP · 2021-02-17 09:02 Full program gives me this on Linux x64 Quoteuser@PC:~$ ./ex Division by zero EDivByZero Program is Code: Pascal  [Select][+][-]window.onload = function(){var x1 = document.getElementById("main_content_section"); if (x1) { var x = document.getElementsByClassName("geshi");for (var i = 0; i {$mode objfpc} uses Sysutils;var i : Integer = 0;begin  try    writeln(IntToStr(10 div i));  except    on E:  Exception do      writeln(E.Message+LineEnding+E.ClassName);  end;end.