Я изо всех сил пытаюсь установить std :: fenv переносимым способом.
На основании этой страницы cppreference кажется, что fesetexceptflag(const std::fexcept_t*,int)
должен помочь мне сделать трюк , С другой стороны, я обнаружил, что GNU предлагает также функцию feenableexcept(int)
. Насколько я понимаю, feenablexcept
- это спецификация GNU c, и, хотя у меня весьма вероятность того, что я всегда буду иметь доступ к вещам 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
? Насколько я понимаю, он захватывает все биты в первом аргументе, которые активны во втором аргументе, и помещает их в fenv (что, похоже, и происходит). Но тогда это кажется неэффективным. С другой стороны, версия 2 имеет fenv с маской 0 и все же успешно поднимает SIGFPE. Я очень смущен.
Я использую g cc 8.2.0 на linux машине (Red Hat), если это может помочь.