std::fenv をポータブルな方法で設定しようとして苦労しています。
このcppreference ページに基づいて、それはfesetexceptflag(const std::fexcept_t*,int)
私がトリックを行うのに役立つはずです. 一方で、GNU にもそのfeenableexcept(int)
機能があることを知りました。私の理解では、それfeenablexcept
はGNU固有のものであり、常にGNUのものにアクセスできる可能性が非常に高いですが、stdのものだけを使用したいと思っていましたfesetexceptflag
。私は小さなテストを書きましたが、feenableexcept
アプローチは機能しますが、fesetexceptflag
機能しないことがわかりました。2 つの例を次に示します。fesetexceptflag
バージョン 1 ( ) とバージョン 2 ( feenableexcept
)を取得するには、main の先頭にある 2 行のコメントを入れ替えます。
#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
か? 私の理解では、2番目の引数でアクティブな最初の引数のすべてのビットを取得し、それらをfenvに入れます(これが起こるようです)。しかし、それでは効果がないようです。一方、バージョン 2 はマスク fenv が 0 ですが、SIGFPE を上げることに成功しています。私はとても混乱しています。
Linux マシン (Red Hat) で gcc 8.2.0 を使用しています。