Jump to content
Joao Lira

'Floating point division by zero' when running script

Recommended Posts

Posted (edited)

Hello,

 

I am starting playing with 'P4D', and I am using 'PyScripter' to test the scripts that I'll eventually use in my Delphi applications. I have some questions because of an error I got when running one script:

 

1) Is 'Demo01' supposedly to run without problems every script that you can run through 'PyScripter'? I have a script that runs flawlessly on 'PyScripter' but it is raising 'Floating point division by zero' error when running with 'Demo01' on 'P4D';

2) Is there some limitation on the scripts that 'P4D' can execute?


I am using Delphi 10.3.3

 

Thank you for any help.

 

  Regards,

  Joao Lira.

2022-01-06_112654 - Floating point division by zero error.jpg

Edited by Joao Lira

Share this post


Link to post

This is just going to be the age old issue that most Windows code expects floating point exceptions to be masked, and Delphi's RTL unmasks them. So, mask floating point exceptions when you call into Python, and unmask them when the Python call returns. Or just mask them always if you don't care about floating point exceptions.

 

Of course, the floating point support for changing floating point control state is not thread safe in the Delphi RTL as I have been saying for more than a decade now.

  • Like 4

Share this post


Link to post

 

9 hours ago, David Heffernan said:

mask floating point exceptions when you call into Python,

P4D provides the MaskFPUExceptions function for that purpose.

  • Like 1

Share this post


Link to post

Thank you, David and pyscripter!

 

I didn't know about this 'MaskFPUExceptions procedure. I am still studying 'P4D', so I will take a while to use it without consulting the available stuff about it.  I like demos as a complement to new knowledge, but I learn more when I read, haha! Is there some book you wrote and we can purchase about 'Python4Delphi' pyscripter? Have you thought about it as a way to support even more this GREAT project? 'Python4Delphi' is, without doubt, one of the GREAT pieces of Delphi software EVER! Kudos to you!

After calling 'MaskFPUExceptions' before and after the 'PythonEngine1.ExecString' it worked as expected!

 

Regards,

Joao Lira.

Share this post


Link to post
On 1/6/2022 at 4:47 PM, David Heffernan said:

Of course, the floating point support for changing floating point control state is not thread safe in the Delphi RTL as I have been saying for more than a decade now.

I am very worried by David H's posting here. But also this could explain an issue I've had on a system for a long time that calls a 3rd party dll that I suspect creates it's own threads. This seems to at random times generate unexpected windows "exception" messages.

The documentation at https://docwiki.embarcadero.com/RADStudio/Alexandria/en/About_Floating-Point_Arithmetic is pretty good at telling you HOW to change floating point exceptions but not at all clear at what to set them to!

Do you recommend when calling external 3rd party dlls that you make a call to SetExceptions() with a value of zero, storing the result (the current settings) into some local variable) before calling the 3rd party dll and then a call to SetExceptions passing the value saved in the local value as soon as the dll completes ?

You may well choose to answer as an experienced Delphi programmer - any advice for me writting in C++ (using classic,, clang32 and clang64 compilers for different apps) would be welcome too.

Thinking about the mulit-threading floating point interaction, surely the only way to achieve this would be to make sure the floating point unit is correctly configured before every floating point operation - a major overhead. I am still pondering this....


 

Share this post


Link to post
53 minutes ago, Roger Cigol said:

Do you recommend when calling external 3rd party dlls that you make a call to SetExceptions() with a value of zero, storing the result (the current settings) into some local variable) before calling the 3rd party dll and then a call to SetExceptions passing the value saved in the local value as soon as the dll completes ?

I set the floating point control state to the Windows default (which masks exceptions) before calling any external library, and then restore it when those calls return. In order for this to work reliably in a multi-threaded environment you need to do some serious RTL patching to fix the thread safety issues.

53 minutes ago, Roger Cigol said:

Thinking about the mulit-threading floating point interaction, surely the only way to achieve this would be to make sure the floating point unit is correctly configured before every floating point operation - a major overhead. I am still pondering this....

No, it is possible to fix the RTL so that you don't require such an invasive solution as you imagine. My numerical software does this.

 

Many years ago I submitted a QC report with the attached document which explains how to fix it. Embarcadero have done nothing yet, although deleting QC meant that my report disappeared from public view!

Rethinking Delphi Floating Point Control Register Management.pdf

Edited by David Heffernan
  • Like 1

Share this post


Link to post

[pdf] That's a very interesting read, thank you

I think your statement about what you do to the floating point control state is what I am trying to achieve with my use of the two SetExceptions() calls.

Share this post


Link to post

Hi @David Heffernan, My pondering continued (and continues). Can you confirm that I am correct in concluding that it is the application (ie task) responsibility to maintain the correct FPU exception settings amongst threads it uses but it is the operating system's responsibility to maintain the FPU settings when process time is switched from one task to another. If this is the case then this makes sense to me and explains why applying the fixes so well outlined in your pdf would make a lot of sense.

Share this post


Link to post

Create an account or sign in to comment

You need to be a member in order to leave a comment

Create an account

Sign up for a new account in our community. It's easy!

Register a new account

Sign in

Already have an account? Sign in here.

Sign In Now

×