我正在努力尝试以便携式方式设置 std::fenv 。
基于这个cppreference 页面,似乎fesetexceptflag(const std::fexcept_t*,int)
应该可以帮助我解决问题。另一方面,我发现 GNU 也提供了这个feenableexcept(int)
功能。我的理解是feenablexcept
GNU 特定的,虽然我很可能总是可以访问 GNU 的东西,但我希望只使用 std 的东西,也就是说,坚持使用fesetexceptflag
. 我写了一个小测试,发现该feenableexcept
方法有效,而该方法fesetexceptflag
无效。这是两个例子。交换 main 开头的两行注释,得到版本 1 ( fesetexceptflag
) 和版本 2 ( feenableexcept
):
#include <cfenv>
#include <csignal>
#include <cstdio>
void signal_handler (int signum) {
printf ("signal %d caught.\n",signum);
exit(1);
}
int main(int,char**){
std::fexcept_t my_flag = FE_DIVBYZERO;
fesetexceptflag(&my_flag,FE_ALL_EXCEPT); // Uncomment this for version 1
// feenableexcept(my_flag); // Uncomment this for version 2
int mask = fetestexcept(FE_ALL_EXCEPT)
printf("current mask: %d\n",mask);
printf("mask is FE_DIVBYZERO: %s\n",mask==FE_DIVBYZERO ? "yes" : "no");
signal(SIGFPE, signal_handler);
double one = 1.0;
double zero = 0.0;
double my_inf = one/zero;
printf("All done!\n");
return 0;
}
版本 1 输出:
current mask: 4
mask is FE_DIVBYZERO: yes
All done!
版本 2 输出:
current mask: 0
mask is FE_DIVBYZERO: no
signal 8 caught.
因此,似乎版本 1 在 fenv 中正确设置了异常标志,但未能引发 SIGFPE,而版本 2 未设置异常标志,但确实引发了 SIGFPE。这里发生了什么事?我是否误解了 的文档fesetexceptflag
?我的理解是,它会抓取第一个 arg 中在第二个 arg 中处于活动状态的所有位,并将它们放入 fenv 中(这似乎正在发生)。但是,它似乎无效。另一方面,版本 2 具有 0 掩码 fenv,但成功提高了 SIGFPE。我很困惑。
我在 linux 机器(Red Hat)上使用 gcc 8.2.0,如果有帮助的话。