|
|
Home » Extra libraries, Code snippets, applications etc. » C++ language problems and code snippets » Capture division by zero
Capture division by zero [message #55184] |
Fri, 16 October 2020 09:15 |
|
koldo
Messages: 3398 Registered: August 2008
|
Senior Veteran |
|
|
I would like to capture floating point errors.
For now in case of error the program execution follows, but you can find in the doubles, things like INF or NAN.
This behaviour is very conservative for my apps, and I'd prefer in some situations to capture these situations stopping the execution.
I have tried it unsuccessfully using:
- signal(SIGFPE, ...)
- _controlfp_s()
- _set_se_translator()
Any help will be acknowledged!
PD. Somebody could say "just check that all data is adequate before using it in division, sqrt, ...". That's true, but difficult and cumbersome in some situations using uncontrolled data sources where sometimes even doing lots of "if" to check the consistency of data, that's not enough.
Best regards
Iñaki
|
|
|
|
Re: Capture division by zero [message #55206 is a reply to message #55184] |
Sun, 18 October 2020 21:21 |
|
Klugier
Messages: 1083 Registered: September 2012 Location: Poland, Kraków
|
Senior Contributor |
|
|
Hello Koldo,
From my personal experience you should identify all the places when division by zero can occurred and handle error separately. To find all places you should use static analyzer. I saw that cppcheck and clang-tidy have tools to detect problem such this.
I also suggest to cover each of the code that can cause division by zero problem with unit tests. Some time ago I added plugin/gtest to the bazaar to make code more bulletproof. One of the reason programmers use unit tests is to test corner cases easily.
Resources:
- https://sourceforge.net/p/cppcheck/wiki/ListOfChecks/ (Just search of division)
Klugier
U++ - one framework to rule them all.
[Updated on: Sun, 18 October 2020 21:40] Report message to a moderator
|
|
|
Re: Capture division by zero [message #55208 is a reply to message #55203] |
Sun, 18 October 2020 21:38 |
|
koldo
Messages: 3398 Registered: August 2008
|
Senior Veteran |
|
|
Thank you Didier, now it works
I have added some additional exception handling in DEBUG mode in SysInfo activated with ExceptionHandler() call.
It includes floating point exception handling.
It might be worth including something like this in main U++, that already includes signal(SIGFPE and other, only valid in Linux.
Best regards
Iñaki
[Updated on: Sun, 18 October 2020 21:38] Report message to a moderator
|
|
|
Re: Capture division by zero [message #55212 is a reply to message #55208] |
Mon, 19 October 2020 07:57 |
|
koldo
Messages: 3398 Registered: August 2008
|
Senior Veteran |
|
|
Quote:From my personal experience you should identify all the places when division by zero can occurred and handle error separately. I agree with you. However the DEBUG mode serves to capture unexpected situations, and this is to add more power to DEBUG mode detection of unexpected and nasty events. In addition to numerical errors, I have included unhandled exceptions, pure virtual functions and invalid parameter handler.
As soon as I tried it with one of my applications, I found a division by zero in an initialization that, by pure luck, had never caused any problem. This alone has been worth the effort, and I think I will capture many more ugly situations like this.
Edit: PD: In a perfect world, DEBUG would be useless
Best regards
Iñaki
[Updated on: Mon, 19 October 2020 08:18] Report message to a moderator
|
|
|
Re: Capture division by zero [message #55216 is a reply to message #55212] |
Mon, 19 October 2020 20:54 |
Didier
Messages: 690 Registered: November 2008 Location: France
|
Contributor |
|
|
Hello Koldo and Klugier,
I agree with Koldo, although unit testing is a must have, you cannot assume that ALL is tested 100% and that it will stay that way in the future (specially and very big projects.
So adding so additionnal checks that are application wide is always a good path.
In addition to catching signals I would also print the stack trace automatically (and eventually write automatically to a file) : this is very usefull in production envs (You can get better knowledge of what went wrong at you're clients site)
Although in release mode stacktrace is less precise (du to optimisations), it is stille very helpfull (as long as you conserve the debug info associated to you're release code)
[Updated on: Mon, 19 October 2020 20:56] Report message to a moderator
|
|
|
|
|
|
|
Re: Capture division by zero [message #55274 is a reply to message #55184] |
Mon, 26 October 2020 23:51 |
|
Klugier
Messages: 1083 Registered: September 2012 Location: Poland, Kraków
|
Senior Contributor |
|
|
Hello Koldo,
Influential people think that divisions by zero or negative square roots are admissible in a good code. I do not agree.
This is not the problem. Error handling or problematic value handling is very important. In production software you should always do that without compromising. The problem with "CrashHandler" is that it forces error handling to all package consumers. It is not even an option - you just create global variable:
static CrashHandler crash;
Library or component provider should avoid it at all cost. You should in the documentation tell that certain function could raise exception or returns error value. If your code could read external value and then it could cause problem you are obligated to validate it and in case of problem do something with it.
At the beginning of the thread I suggest to use static analyzer to find all this divided by zero problems and handle it properly. This is the best strategy for library and professional software. I agree that minidumps are extremely helpful to identify problems on production, but it must be handled on application level - never on library level.
/**
* PUBLIC API DOCUMENTATION
* In case when divider is 0 std::runtime_error is thrown.
*/
int Calculate(int divider)
{
if (divider == 0)
{
throw std::runtime_error("Calculate(): Divider can not be zero...");
}
return 20 / divider;
}
// Now the client could deiced what to do with the exception - it can be handled locally or globally in main function, but it is still the consumer choice what to do with it
// In case of global handler provided by library the decisions were taken from application creator.
// ... Below line may even decrese the performance, because on each new allocation NewHandler will be called.
std::set_new_handler(NewHandler);
std::set_unexpected(UnexpectedHandler); // <- What if somebody defines this handler and you overriding it - you should check this at least...
To be clear my overall goal is to pick up the quality of our packages. Never decrees or compromise on error handling, so you are my ally.
Klugier
U++ - one framework to rule them all.
[Updated on: Mon, 26 October 2020 23:56] Report message to a moderator
|
|
|
|
|
|
|
Re: Capture division by zero [message #55295 is a reply to message #55184] |
Tue, 27 October 2020 18:58 |
Didier
Messages: 690 Registered: November 2008 Location: France
|
Contributor |
|
|
Hello Koldo,
Quote:f your code considers these situations as normal, my friend, you are screwed
I don't know what made you think that was my point of view, and it is not at all my vision (rather the contrary), the only thing I say is that code comes from everywhere and quality is not always as it should be.
So everything that can be done to detect and correct this must be done and made available (including detecting divisions by 0, overflows, ...)
And besides, no one is perfect, errors are everywhere all the time (especially with big teams): so you have to deal with them
|
|
|
Re: Capture division by zero [message #55297 is a reply to message #55295] |
Tue, 27 October 2020 19:21 |
|
koldo
Messages: 3398 Registered: August 2008
|
Senior Veteran |
|
|
Didier wrote on Tue, 27 October 2020 18:58Hello Koldo,
Quote:f your code considers these situations as normal, my friend, you are screwed
I don't know what made you think that was my point of view, and it is not at all my vision (rather the contrary), the only thing I say is that code comes from everywhere and quality is not always as it should be.
So everything that can be done to detect and correct this must be done and made available (including detecting divisions by 0, overflows, ...)
And besides, no one is perfect, errors are everywhere all the time (especially with big teams): so you have to deal with them
Sorry Didier
There must be a misunderstanding. My point of view is debugging all errors, including floating point.
Absolutely I was not referring to you and your point of view.
Best regards
Iñaki
|
|
|
Re: Capture division by zero [message #58696 is a reply to message #55277] |
Mon, 25 July 2022 03:37 |
jjacksonRIAB
Messages: 225 Registered: June 2011
|
Experienced Member |
|
|
Quote:
The calculation of your bank account balance is infinite
Anyone have an opinion on this one? I'm of the opinion that floats should not be used to represent any kind of currency or bank balance and I tended to replace them in C# with Decimal when I worked for an accounting department. I haven't checked but does U++ have a fixed-point decimal type for dealing with currency and other numbers where float accuracy is not good enough? If not maybe one should be made.
EDIT Just realized I didn't provide a reason why not to use them. What I found is it wasn't NaN-stuff (though that could be a problem), but mainly because floats have a tendency to accumulate errors over successive calculations - that and the fact that you might want Banker's rounding or some other kind of rounding algorithm. Another reason I ditched floats is because they can't produce consistent results on different architectures, different CPUs, different families of CPUs, or even the same CPU. In one particularly egregious case I had a bad video driver produce wildly inaccurate results on a single accountant's machine and I could only guess that some of the computation was being offloaded to the GPU.
Looking further into C#'s decimal type, it appears it uses arbitrary precision floats underneath. There are number of libraries for doing this in C++, some listed here:
https://en.wikipedia.org/wiki/List_of_arbitrary-precision_ar ithmetic_software
Since they are still floats it's not a cure all for the problem of cumulative errors so I was wrong about that. That said, I still think a fixed-point decimal class would be desirable.
[Updated on: Mon, 25 July 2022 04:49] Report message to a moderator
|
|
|
Re: Capture division by zero [message #58697 is a reply to message #58696] |
Mon, 25 July 2022 09:39 |
|
mirek
Messages: 14105 Registered: November 2005
|
Ultimate Member |
|
|
jjacksonRIAB wrote on Mon, 25 July 2022 03:37
Anyone have an opinion on this one? I'm of the opinion that floats should not be used to represent any kind of currency or bank balance and I tended to replace them in C# with Decimal when I worked for an accounting department. I haven't checked but does U++ have a fixed-point decimal type for dealing with currency and other numbers where float accuracy is not good enough? If not maybe one should be made.
Interesting question. For what is worth, I was doing applications dealing with money for years and while I know the theory, I have simple used double the whole time, to no ill effects.
I guess that in the end, you are usually rounding to 2 decimals after the point. You would need to sum millions of values to get a difference in printed output, so for the most time, it is just fine.
That said, Decimal datatype would be fine.
BTW, I do not think float or not float is the issue here, but underlying representation. Now I was not looking into this for some time, but I think that to be "financial correct" you need decimal representation instead of binary (some form of BCD) so that you can represent decimal fractional numbers exactly.
Mirek
[Updated on: Mon, 25 July 2022 09:39] Report message to a moderator
|
|
|
|
Goto Forum:
Current Time: Fri Nov 01 01:39:04 CET 2024
Total time taken to generate the page: 0.02611 seconds
|
|
|