0

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.

Cristian
  • 654
  • 1
  • 13
  • 30
  • 1
    8 is `SIGFPE`. Maybe you should look up what the argument `s` *is* – user253751 Jul 09 '20 at 15:55
  • if i remove the if statement it prints `"sig: 8"` so the argument is `s` is `8` – Cristian Jul 09 '20 at 15:59
  • 1
    Division-by-zero is undefined behavior which means that formally there is no way to detect it after-the-fact or recover from it. The compiler can just assume it will never happen. – Johan Jul 09 '20 at 15:59
  • 2
    Integer division by zero is undefined behaviour. Not something you can catch and handle. You must prevent it from ever happening. See also https://stackoverflow.com/a/3004122/5910058 – Jesper Juhl Jul 09 '20 at 16:02
  • Does this answer your question? [How to get further information on SIGFPE signal?](https://stackoverflow.com/questions/30628167/how-to-get-further-information-on-sigfpe-signal) – Paul Sanders Jul 09 '20 at 16:08
  • 1
    _thanks but I already know the listed macros_ Point is, these are passed as the _second_ parameter to your signal handler, not the first, as the link explains. And for Windows, you can use `__try` ... `__except`, see: https://learn.microsoft.com/en-us/cpp/cpp/structured-exception-handling-c-cpp?view=vs-2019 – Paul Sanders Jul 09 '20 at 16:33
  • Oh now I see, let me edit – Cristian Jul 09 '20 at 16:38
  • Actually #include is fine, but #define for libraries is what most people cannot stand, please do not use #define.... @Cristian – Yunfei Chen Jul 09 '20 at 17:12
  • @YunfeiChen what do you mean? I'm not using macros or `#define`'s in my code; `#include ` is for including a header file and `#define` is for macro definition or symbolic constants definitions. I didn't quite understand what you where trying to say. Perhaps you meant, do not ever create macros or symbolic constants, to which I'd reply *sometimes it's good to have a preprocessor because it saves you a lot of time when you need to write the same thing over and over*. I guess `#include` is fine because there's no way to work with multiple files without it... – Cristian Jul 09 '20 at 20:33
  • 1
    @Cristian If you do something like #include it is usually fine in the programming world, but just an advice for you do not pick of the habit of doing something like: #define malloc(x) my_debug_malloc(x, __FILE__, __LINE__) #define free(x) my_debug_free(x, __FILE__, __LINE__) #define begin() x = 0 #define end() x = 17 Just don't okay, makes your code unreadable.... – Yunfei Chen Jul 09 '20 at 21:51
  • 1
    @Cristian Thats one of the reasons some programmers hate macros..... – Yunfei Chen Jul 09 '20 at 22:43

1 Answers1

2

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.

tadman
  • 208,517
  • 23
  • 234
  • 262
  • Could you please add the line "BSD systems provide the SIGFPE handler with an extra argument that distinguishes various causes of the exception. In order to access this argument, you must define the handler to accept two arguments, which means you must cast it to a one-argument function type in order to establish the handler. The GNU C Library does provide this extra argument, but the value is meaningful only on operating systems that provide the information (BSD systems and GNU systems)." – Cristian Jul 09 '20 at 16:34
  • It's in the link you provided and I think it's important – Cristian Jul 09 '20 at 16:35
  • That's a good observation and I think your comment helps establish it. – tadman Jul 09 '20 at 17:13