完美的除法抛出浮点异常
Perfectly fine division throws floating point exception
我有一个神秘的浮点异常。
我通过这样做来捕捉它:
feenableexcept( FE_DIVBYZERO | FE_INVALID | FE_OVERFLOW );
然后这段代码中的第二个分区(最后一行):
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;
抛出如下 SIGFPE:
除数(在控制台中打印出来,也由 gdb 打印)是 1.0839119,分子是 -1.05979919,所以我看不出有什么问题。
额外的怪异:
- 不会在 -O0 调试版本中发生。
- 如果我通过 valgrind运行 应用程序
则不会发生
编译器:
$ clang -v
clang version 6.0.0-1ubuntu2 (tags/RELEASE_600/final)
和编译器选项:
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
为什么会发生这种 FPE?我能想到的唯一原因是,即使它是标量除法,clang 也会生成 SIMD 除法。如果 XMM 寄存器中的其他通道包含零分母怎么办?如果任何通道除以零,SIMD 划分是否会生成 FPE?如果是这样,我怎样才能捕获 FPE?
clang version 10 compiler option 将确保未使用的通道不会导致 FP 异常:
-ffp-exception-behavior=maytrap
我已经测试过了,它可以工作:它可以防止虚假的浮点异常。
我有一个神秘的浮点异常。 我通过这样做来捕捉它:
feenableexcept( FE_DIVBYZERO | FE_INVALID | FE_OVERFLOW );
然后这段代码中的第二个分区(最后一行):
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;
抛出如下 SIGFPE:
除数(在控制台中打印出来,也由 gdb 打印)是 1.0839119,分子是 -1.05979919,所以我看不出有什么问题。
额外的怪异:
- 不会在 -O0 调试版本中发生。
- 如果我通过 valgrind运行 应用程序 则不会发生
编译器:
$ clang -v
clang version 6.0.0-1ubuntu2 (tags/RELEASE_600/final)
和编译器选项:
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
为什么会发生这种 FPE?我能想到的唯一原因是,即使它是标量除法,clang 也会生成 SIMD 除法。如果 XMM 寄存器中的其他通道包含零分母怎么办?如果任何通道除以零,SIMD 划分是否会生成 FPE?如果是这样,我怎样才能捕获 FPE?
clang version 10 compiler option 将确保未使用的通道不会导致 FP 异常:
-ffp-exception-behavior=maytrap
我已经测试过了,它可以工作:它可以防止虚假的浮点异常。