Floating point exceptions - gcc bug?

2019-06-27 01:18发布

问题:

Consider the following code:

#include <fenv.h>
#include <stdio.h>
int main()
{
    #pragma STDC FENV_ACCESS ON
    1.0/0.0;
    printf("%x\n", fetestexcept(FE_ALL_EXCEPT));
}

I would expect it to print a nonzero value corresponding to FE_DIVBYZERO, but it prints 0. Changing the second line of main to double x = 1.0/0.0; gives the expected behavior. Is this permitted, or is it a bug?

Edit: For what it's worth, at first it may seem that in most real-world code, the operations which might cause fenv exceptions to be raised could not be optimized out, so one could safely perform large computations and check at the end whether any overflow, div-by-zero, etc. happened. However, things get messy and a real issue emerges when you consider inlining and optimization. If such a function got inlined in a situation where it would always end up dividing by zero due to constant arguments, gcc might get really smart and optimize the whole inlined function essentially to return INFINITY; without raising any exceptions.

回答1:

This is expected behaviour. gcc doesn't evaluate the expression, because it would have nothing to do with it afterwards.

If you compile with "-Wall", it warns you that the statement has no effect, and that it ignores the pragma statement.

GCC is not fully C99 compliant. For more information, see: http://gcc.gnu.org/c99status.html

For the issue of implementing this behaviour, see: http://gcc.gnu.org/bugzilla/show_bug.cgi?id=20785



回答2:

This is something of a gray area. A strict reading of the floating-point environment section of the standard could easily lead one to believe that this is a bug. I suspect that the GCC maintainers will disagree with that reading, however.

For that matter, I'm not sure that GCC even claims to understand the FENV_ACCESS pragma. Certainly earlier versions did not.



回答3:

Compiling with -Wall on gcc 4.6.0 says:

f.c:5:0: warning: ignoring #pragma FENV_ACCESS ON [-Wunknown-pragmas]

According to the GCC info pages:

* `The default state for the `FENV_ACCESS' pragma (C99 7.6.1).'

 This pragma is not implemented, but the default is to "off" unless
 `-frounding-math' is used in which case it is "on".

Unfortuantely, -frounding-math does not seem to have any effect on your program.

Arguably a compiler bug; I would ask on one of the GCC mailing lists.



回答4:

It's possible that your compiler has optimized the original version out. Recognizing that the two constants are not "used" in any non-trivial sense, it may not even exist in the compiled binary.

The second example changes that, by actually assigning the operation to a variable.



回答5:

I think the expression is getting optimised away in the first case, but not in the second. I can reproduce your results with gcc 4.2 with gcc -O0, but if I go to gcc -O3 then I get 0 in both cases.