Here is a simple piece of code where a division by zero occurs. I'm trying to catch it :
#include <iostream>
int main(int argc, char *argv[]) {
int Dividend = 10;
int Divisor = 0;
try {
std::cout << Dividend / Divisor;
} catch(...) {
std::cout << "Error.";
}
return 0;
}
But the application crashes anyway (even though I put the option -fexceptions of MinGW).
Is it possible to catch such an exception (which I understand is not a C++ exception, but a FPU exception) ?
I'm aware that I could check for the divisor before dividing, but I made the assumption that, because a division by zero is rare (at least in my app), it would be more efficient to try dividing (and catching the error if it occurs) than testing each time the divisor before dividing.
I'm doing these tests on a WindowsXP computer, but would like to make it cross platform.
It's not an exception. It's an error which is determined at hardware level and is returned back to the operating system, which then notifies your program in some OS-specific way about it (like, by killing the process).
I believe that in such case what happens is not an exception but a signal. If it's the case: The operating system interrupts your program's main control flow and calls a signal handler, which - in turn - terminates the operation of your program.
It's the same type of error which appears when you dereference a null pointer (then your program crashes by SIGSEGV signal, segmentation fault).
You could try to use the functions from <csignal> header to try to provide a custom handler for the SIGFPE signal (it's for floating point exceptions, but it might be the case that it's also raised for integer division by zero - I'm really unsure here). You should however note that the signal handling is OS-dependent and MinGW somehow "emulates" the POSIX signals under Windows environment.
Here's the test on MinGW 4.5, Windows 7:
#include <csignal>
#include <iostream>
using namespace std;
void handler(int a) {
cout << "Signal " << a << " here!" << endl;
}
int main() {
signal(SIGFPE, handler);
int a = 1/0;
}
Output:
Signal 8 here!
And right after executing the signal handler, the system kills the process and displays an error message.
Using this, you can close any resources or log an error after a division by zero or a null pointer dereference... but unlike exceptions that's NOT a way to control your program's flow even in exceptional cases. A valid program shouldn't do that. Catching those signals is only useful for debugging/diagnosing purposes.
(There are some useful signals which are very useful in general in low-level programming and don't cause your program to be killed right after the handler, but that's a deep topic).
Dividing by zero is a logical error, a bug by the programmer. You shouldn't try to cope with it, you should debug and eliminate it. In addition, catching exceptions is extremely expensive- way more than divisor checking will be.
You can use Structured Exception Handling to catch the divide by zero error. How that's achieved depends on your compiler. MSVC offers a function to catch Structured Exceptions as catch(...) and also provides a function to translate Structured Exceptions into regular exceptions, as well as offering __try/__except/__finally. However I'm not familiar enough with MinGW to tell you how to do it in that compiler.
There's isn't a
language-standard way of catching
the divide-by-zero from the CPU.
Don't prematurely "optimize" away a
branch. Is your application
really CPU-bound in this context? I doubt it, and it isn't really an
optimization if you break your code.
Otherwise, I could make your code
even faster:
int main(int argc, char *argv[]) { /* Fastest program ever! */ }
Divide by zero is not an exception in C++, see https://web.archive.org/web/20121227152410/http://www.jdl.co.uk/briefings/divByZeroInCpp.html
Somehow the real explanation is still missing.
Is it possible to catch such an exception (which I understand is not a C++ exception, but a FPU exception) ?
Yes, your catch block should work on some compilers. But the problem is that your exception is not an FPU exception. You are doing integer division. I don’t know whether that’s also a catchable error but it’s not an FPU exception, which uses a feature of the IEEE representation of floating point numbers.
On Windows (with Visual C++), try this:
BOOL SafeDiv(INT32 dividend, INT32 divisor, INT32 *pResult)
{
__try
{
*pResult = dividend / divisor;
}
__except(GetExceptionCode() == EXCEPTION_INT_DIVIDE_BY_ZERO ?
EXCEPTION_EXECUTE_HANDLER : EXCEPTION_CONTINUE_SEARCH)
{
return FALSE;
}
return TRUE;
}
MSDN: http://msdn.microsoft.com/en-us/library/ms681409(v=vs.85).aspx
Well, if there was an exception handling about this, some component actually needed to do the check. Therefore you don't lose anything if you check it yourself. And there's not much that's faster than a simple comparison statement (one single CPU instruction "jump if equal zero" or something like that, don't remember the name)
To avoid infinite "Signal 8 here!" messages, just add 'exit' to Kos nice code:
#include <csignal>
#include <iostream>
#include <cstdlib> // exit
using namespace std;
void handler(int a) {
cout << "Signal " << a << " here!" << endl;
exit(1);
}
int main() {
signal(SIGFPE, handler);
int a = 1/0;
}
As others said, it's not an exception, it just generates a NaN or Inf.
Zero-divide is only one way to do that. If you do much math, there are lots of ways, like
log(not_positive_number), exp(big_number), etc.
If you can check for valid arguments before doing the calculation, then do so, but sometimes that's hard to do, so you may need to generate and handle an exception.
In MSVC there is a header file #include <float.h> containing a function _finite(x) that tells if a number is finite.
I'm pretty sure MinGW has something similar.
You can test that after a calculation and throw/catch your own exception or whatever.
Related
I have the following piece of c++ code:
void update(const int step, const int total) const
{
double s = static_cast<double>(step);
double t = static_cast<double>(total);
std::cout << s/t <<"------\n";
// etc...
}
I am using the intel c++ compiler with the -fp-trap=all flag activated. When running the code through gdb I get the following error:
Program received signal SIGFPE, Arithmetic exception.
0x000000000040ee07 in NilDa::progressBar::update (this=0x7fffffffbc9c, step=1, total=60000) at /home/d2d/dev/NilDa/sources/utils/progressBar.h:69
69 std::cout << s/t <<"------\n";
I don't really understand what is going on. The division seems to be well defined.
I'm assuming you're using the Intel C++ compiler (I'm not aware of any other compiler having such a flag).
If so you can take a look here: https://software.intel.com/content/www/us/en/develop/documentation/cpp-compiler-developer-guide-and-reference/top/compiler-reference/compiler-options/compiler-option-details/floating-point-options/fp-trap-qfp-trap.html#
As stated within that documentation the argument all inherits the trap for inexact results ([no]inexact)
Enables or disables the IEEE trap for inexact result.
Since 1/60000 can not be represented by an floating point number the result is inexact (1.66667e-05).
I was trying to handle the integer division by zero (please don't judge, I was told I had to use <csignal> lib and I couldn't just use an if statement), but I needed to make sure the program would keep running (even though it's a very bad practice), instead of crashing or closing. The weird part is that the program should only handle division by zero but should exit for every other type of SIGFPE.
SideNote: Now, I have no idea why they use names like FPU or FE or FPE when referring to integer "exceptions" (or I should say interrupts) since the standard says clearly that dividing a floating point number should return either inf or nan for 0 / 0 (tell me if I'm wrong).
Anyway, I wrote this test code so I could better understand what I needed to do before the actual implementation. I know, it's weird to have x as a global variable but if I don't reset it, it will keep calling handle for no reason like forever....
#include <iostream>
#include <csignal>
using namespace std;
int x = 0;
void handle(int s);
int main(int argc, char * argv[]) {
signal(SIGFPE, handle);
cout << "Insert 0: ";
cin >> x; // here I would input 0, so the program can compile
x = 5 / x;
cout << "X: " << x << endl;
return 0;
}
void handle(int s) {
if (s != FPE_INTDIV) exit(1);
cout << "sig: " << s << endl;
x = 1;
}
As you can see I used FPE_INTDIV to rule out every other type of exceptions, but it doesn't work.
Eventually I discovered that FPE_INTDIV is a symbolic constant for 7 (that's what vs-code's intellisense tells me) and if I were to print the value of s, that would be 8. I discovered that, strangely enough, 8 is the value for FPE_INTOVF on which the documentation states that it's specifically designed for integer overflows.
Why on earth is the symbolic value for overflows used for integer division if there is a symbolic for integer division? What am I missing? Did someone mess up the values in the library? Am I using the wrong macros?
I should also mention, this code compiles fine with clang++ and g++ but when compiled on a Windows computer with cl, it tells me there's no macro for FPE_INTDIV.
How can I be sure of what I'm doing and write a cross platform solution that works?
I already feel like an idiot.
It's defined as:
The SIGFPE signal reports a fatal arithmetic error. Although the name is derived from “floating-point exception”, this signal actually covers all arithmetic errors, including division by zero and overflow. If a program stores integer data in a location which is then used in a floating-point operation, this often causes an “invalid operation” exception, because the processor cannot recognize the data as a floating-point number.
There's no reason for it to be labelled specifically FPE but these sorts of labels can evolve in unpredictable ways. I wouldn't read too much into it.
These signals are part of the POSIX standard and may not be fully supported or implemented in Windows. The Windows implementation of these support facilities is lacking in a number of areas, like how fork() is unsupported.
Here is a simple piece of code where a division by zero occurs. I'm trying to catch it :
#include <iostream>
int main(int argc, char *argv[]) {
int Dividend = 10;
int Divisor = 0;
try {
std::cout << Dividend / Divisor;
} catch(...) {
std::cout << "Error.";
}
return 0;
}
But the application crashes anyway (even though I put the option -fexceptions of MinGW).
Is it possible to catch such an exception (which I understand is not a C++ exception, but a FPU exception) ?
I'm aware that I could check for the divisor before dividing, but I made the assumption that, because a division by zero is rare (at least in my app), it would be more efficient to try dividing (and catching the error if it occurs) than testing each time the divisor before dividing.
I'm doing these tests on a WindowsXP computer, but would like to make it cross platform.
It's not an exception. It's an error which is determined at hardware level and is returned back to the operating system, which then notifies your program in some OS-specific way about it (like, by killing the process).
I believe that in such case what happens is not an exception but a signal. If it's the case: The operating system interrupts your program's main control flow and calls a signal handler, which - in turn - terminates the operation of your program.
It's the same type of error which appears when you dereference a null pointer (then your program crashes by SIGSEGV signal, segmentation fault).
You could try to use the functions from <csignal> header to try to provide a custom handler for the SIGFPE signal (it's for floating point exceptions, but it might be the case that it's also raised for integer division by zero - I'm really unsure here). You should however note that the signal handling is OS-dependent and MinGW somehow "emulates" the POSIX signals under Windows environment.
Here's the test on MinGW 4.5, Windows 7:
#include <csignal>
#include <iostream>
using namespace std;
void handler(int a) {
cout << "Signal " << a << " here!" << endl;
}
int main() {
signal(SIGFPE, handler);
int a = 1/0;
}
Output:
Signal 8 here!
And right after executing the signal handler, the system kills the process and displays an error message.
Using this, you can close any resources or log an error after a division by zero or a null pointer dereference... but unlike exceptions that's NOT a way to control your program's flow even in exceptional cases. A valid program shouldn't do that. Catching those signals is only useful for debugging/diagnosing purposes.
(There are some useful signals which are very useful in general in low-level programming and don't cause your program to be killed right after the handler, but that's a deep topic).
Dividing by zero is a logical error, a bug by the programmer. You shouldn't try to cope with it, you should debug and eliminate it. In addition, catching exceptions is extremely expensive- way more than divisor checking will be.
You can use Structured Exception Handling to catch the divide by zero error. How that's achieved depends on your compiler. MSVC offers a function to catch Structured Exceptions as catch(...) and also provides a function to translate Structured Exceptions into regular exceptions, as well as offering __try/__except/__finally. However I'm not familiar enough with MinGW to tell you how to do it in that compiler.
There's isn't a
language-standard way of catching
the divide-by-zero from the CPU.
Don't prematurely "optimize" away a
branch. Is your application
really CPU-bound in this context? I doubt it, and it isn't really an
optimization if you break your code.
Otherwise, I could make your code
even faster:
int main(int argc, char *argv[]) { /* Fastest program ever! */ }
Divide by zero is not an exception in C++, see https://web.archive.org/web/20121227152410/http://www.jdl.co.uk/briefings/divByZeroInCpp.html
Somehow the real explanation is still missing.
Is it possible to catch such an exception (which I understand is not a C++ exception, but a FPU exception) ?
Yes, your catch block should work on some compilers. But the problem is that your exception is not an FPU exception. You are doing integer division. I don’t know whether that’s also a catchable error but it’s not an FPU exception, which uses a feature of the IEEE representation of floating point numbers.
On Windows (with Visual C++), try this:
BOOL SafeDiv(INT32 dividend, INT32 divisor, INT32 *pResult)
{
__try
{
*pResult = dividend / divisor;
}
__except(GetExceptionCode() == EXCEPTION_INT_DIVIDE_BY_ZERO ?
EXCEPTION_EXECUTE_HANDLER : EXCEPTION_CONTINUE_SEARCH)
{
return FALSE;
}
return TRUE;
}
MSDN: http://msdn.microsoft.com/en-us/library/ms681409(v=vs.85).aspx
Well, if there was an exception handling about this, some component actually needed to do the check. Therefore you don't lose anything if you check it yourself. And there's not much that's faster than a simple comparison statement (one single CPU instruction "jump if equal zero" or something like that, don't remember the name)
To avoid infinite "Signal 8 here!" messages, just add 'exit' to Kos nice code:
#include <csignal>
#include <iostream>
#include <cstdlib> // exit
using namespace std;
void handler(int a) {
cout << "Signal " << a << " here!" << endl;
exit(1);
}
int main() {
signal(SIGFPE, handler);
int a = 1/0;
}
As others said, it's not an exception, it just generates a NaN or Inf.
Zero-divide is only one way to do that. If you do much math, there are lots of ways, like
log(not_positive_number), exp(big_number), etc.
If you can check for valid arguments before doing the calculation, then do so, but sometimes that's hard to do, so you may need to generate and handle an exception.
In MSVC there is a header file #include <float.h> containing a function _finite(x) that tells if a number is finite.
I'm pretty sure MinGW has something similar.
You can test that after a calculation and throw/catch your own exception or whatever.
I need a sample code, that throws EXCEPTION_FLT_UNDERFLOW. I already have code to handle that exception. Now I need sample, that throws it. Any advises?
Assuming you want actual code that will trigger this:
#include <float.h>
int main()
{
_controlfp_s(NULL, 0, _MCW_EM); // enable all floating point exceptions
float f= 1.0f;
while (f)
{
f/=2.0f;
// __asm fwait; // optional, if you want to trap the underflow sooner
}
return 0;
}
Try:
RaiseException(EXCEPTION_FLT_UNDERFLOW, EXCEPTION_NONCONTINUABLE, 0, NULL);
Even in C99 there is no portable way to do this. This works on Linux:
#define _GNU_SOURCE
#include <fenv.h>
int
main(void)
{
fesetenv(FE_NOMASK_ENV);
feraiseexcept(FE_UNDERFLOW);
return 0;
}
but without the #define _GNU_SOURCE and the fesetenv call (which are not portable), the exception is not thrown (== does not trigger SIGFPE, in Unix terms), it just sets a flag. And no iteration of MSVC supports <fenv.h>, so you're stuck with completely nonstandard on Windows.
That said, there does appear to be a Windows-specific equivalent:
#include <float.h>
#pragma fenv_access (on)
int
main(void)
{
_controlfp_s(0, 0, _MCW_EM); /* throw all floating point exceptions */
/* trigger floating-point underflow here */
}
You will have to cause an underflow condition using actual floating point operations. I don't know how to do that off the top of my head. It would probably be best to do it by hand in assembly language, to avoid interference from the compiler (even more non-portability, yes, but if you're on Windows you probably don't care about any CPU but x86).
throw EXCEPTION_FLT_UNDERFLOW;
After looking at another question on SO (Using NaN in C++) I became curious about std::numeric_limits<double>::signaling_NaN().
I could not get signaling_NaN to throw an exception. I thought perhaps by signaling it really meant a signal so I tried catching SIGFPE but nope...
Here is my code:
double my_nan = numeric_limits<double>::signaling_NaN();
my_nan++;
my_nan += 5;
my_nan = my_nan / 10;
my_nan = 15 / my_nan;
cout << my_nan << endl;
numeric_limits<double>::has_signaling_NaN evaluates to true, so it is implemented on my system.
Any ideas?
I am using ms visual studio .net 2003's C++ compiler. I want to test it on another when I get home.
Thanks!
You can use the _control87() function to enable floating-point exceptions. From the MSDN documentation on _control87():
Note:
The run-time libraries mask all floating-point exceptions by default.
When floating point exceptions are enabled, you can use signal() or SEH (Structured Exception Handling) to catch them.
A word of warning:
Using 3rd party DLLs may silently enable these exceptions. This is especially true for loading DLL's that are written in a language that enables them by default.
I've had that happen in two instances: Printing from an embedded browser control to a HP printer, and registering my DLL (that sets some initial values to NaN) from InnoSetup which is written in Delphi.
From TFM:
cout << "The signaling NaN for type float is: "
<< numeric_limits<float>::signaling_NaN( )
<< endl;
->
The signaling NaN for type float is: 1.#QNAN
where the 'Q' stands for 'Quiet'. Dunno why it would return that, but that's why it doesn't throw an exception for you.
Out of curiosity, does this work better?
const double &real_snan( void )
{
static const long long snan = 0x7ff0000080000001LL;
return *(double*)&snan;
}
The key lies in numeric_limits<T>::has_signaling_NaN. Which value does this have for you? (The MSDN seems to suggest that it's always false for MSVC?)