我可以使用 feenableexcept() 来更改 FPE 环境。然而,两行代码之后,我的 control_word 发生了一些变化。有没有人见过这个并且知道如何阻止它?
fedisableexcept(FE_ALL_EXCEPT);
feenableexcept(FE_DIVBYZERO | FE_OVERFLOW | FE_INVALID); // FE_UNDERFLOW & FE_INEXACT are too common
fegetenv(&tmp_env); // tmp_env.__control_word = 882. As expected
int AA = 1;
fegetenv(&tmp_env); // tmp_env.__control_word = 895. No good
问题可能是多个线程运行程序吗?有没有办法设置默认的 control_word 位,这样它们就不会被覆盖?
我有一个简单的 C++ 程序,它 1) 循环 FPE 方程,2) 捕获 SIGFPE 并打印一些有用的信息,3) 使用 uc_mcontext.fpregs->mxcsr 清除 FPU 状态字,4) 计算有问题的运算符长度然后跳过那个运营商。这样程序可以在不退出的情况下继续运行。
对于最后一次运行,我指定了 feenableexcept(FE_DIVBYZERO); 它似乎在一开始就起作用,但随后某些东西改变了标志并开始捕获其他 FPE。下面是程序输出:
- 0: control_word = 891
The SignalCatcher program is running!
=============================================================
Test 01: (float) 1.0e-300 = 0
=============================================================
Test 02: (float) 1.0e300 = inf
=============================================================
Test 03: acos(1.01f) = nan
=============================================================
0: control_word = 895
1. insn_get_length() = 2
B: Boost stacktrace specific: main in /home/lcordova/bin/signalCatcher/main.cpp L89
F. psiginfo specific: Caught signal 8 with signal code Int_Div-by-zero(1). Exception at address 0x401658 .
Test 04: 1/0 = 1
=============================================================
0: control_word = 895
1. insn_get_length() = 5
B: Boost stacktrace specific: main in /home/lcordova/bin/signalCatcher/main.cpp L92
F. psiginfo specific: Caught signal 8 with signal code FP_Div-by-zero(3). Exception at address 0x4016ad .
Test 05: 1.0f/0.0f = 1
=============================================================
0: control_word = 895
1. insn_get_length() = 4
B: Boost stacktrace specific: in L0
F. psiginfo specific: Caught signal 8 with signal code FP_Invalid(7). Exception at address 0x2b44f640 .
Test 06: sqrt(-1) = 0
=============================================================
0: control_word = 895
1. insn_get_length() = 4
B: Boost stacktrace specific: main in /home/lcordova/bin/signalCatcher/main.cpp L77
F. psiginfo specific: Caught signal 8 with signal code FP_Underflow(5). Exception at address 0x4014f1 .
Test 01: (float) 1.0e-300 = -124.475
=============================================================
0: control_word = 895
1. insn_get_length() = 4
B: Boost stacktrace specific: main in /home/lcordova/bin/signalCatcher/main.cpp L81
F. psiginfo specific: Caught signal 8 with signal code FP_Overflow(4). Exception at address 0x40155d .
Test 02: (float) 1.0e300 = -3.86568e-34
=============================================================
0: control_word = 895
1. insn_get_length() = 4
B: Boost stacktrace specific: acos in L0
F. psiginfo specific: Caught signal 8 with signal code FP_Invalid(7). Exception at address 0x2b46d9fa .
Test 03: acos(1.01f) = nan