I have a mystery floating point exception. I catch it by doing:
feenableexcept( FE_DIVBYZERO | FE_INVALID | FE_OVERFLOW );
Then the second division (last line) in this code:
const float dx = other.px[ j ] - curx;
const float dy = other.py[ j ] - cury;
const float dsqr = dx*dx + dy*dy;
ASSERTM( dsqr > 0.0f, "dx %f dy %f dsqr %f", dx, dy, dsqr );
const float dist = sqrtf( dsqr );
ASSERTM( dist > 0.0f, "dx %f dy %f dsqr %f dist %f", dx, dy, dsqr, dist );
LOGI( "dx %f dy %f dsqr %f dist %f", dx, dy, dsqr, dist );
const float dirx = dx / dist;
const float diry = dy / dist;
Throws a SIGFPE as follows:
The divisor (printed out in console, and also printed by gdb) is 1.0839119 and numerator is -1.05979919 so I don't see what is wrong with that.
For extra weirdness:
- Does not happen in -O0 debug build.
- Does not happen if I run the app through valgrind
Compiler:
$ clang -v
clang version 6.0.0-1ubuntu2 (tags/RELEASE_600/final)
And compiler options:
clang++ -DXWIN -DLANDSCAPE -DUSECOREPROFILE -Dlinux -D_POSIX_C_SOURCE=199309L -D_DEFAULT_SOURCE -DAPPVER=1.00 -DLOGTAG=minimal -I/home/bram/src/stb/ -I/home/bram/include -I/public -I/home/bram/src/dutch-blunt/src -I/home/bram/apps/GBase/src -IPI -I/home/bram/src/ThreadTracer `/home/bram/bin/sdl2-config --cflags` -g -Wall -Wshadow -Wno-conversion -Wno-missing-braces -Wno-old-style-cast -Wno-unknown-pragmas -MMD -MP -O2 -std=c++11 -c -o PI/stars.o PI/stars.cpp
Why is this FPE happening? The only reason I could think of, is that even though it is a scalar division, clang generates a SIMD division. What if the other lanes in the XMM register contain zero denominators? Do SIMD divisions generate FPEs if any of the lanes divides by zero? If so, how can I ever trap FPEs?