3

数値アプリケーションで、計算終了後に浮動小数点例外が発生したかどうかを知りたいです。デフォルトでは、浮動小数点の除算と無効な演算は黙って無視されます。

私の試みは、気になる FPE を有効にし、フラグを設定して SIGFPE を処理し、再度無効にして実行を継続できるようにすることです。

#include <fenv.h>
#include <signal.h>
#include <stdio.h>

int caught = 0;
struct sigaction old_sa;
/* (2) */ fenv_t fenv_hold;

void sighandler()
{
    caught = 1;
    printf("Caught in handler, disabling\n");
    /* (1) */ fedisableexcept(FE_ALL_EXCEPT);
    /* (2) */ feholdexcept(&fenv_hold);
    sigaction(SIGFPE, &old_sa, NULL);
}

int main(void)
{
    struct sigaction sa;
    volatile double a=1, b=0;

    sigemptyset(&sa.sa_mask);
    sa.sa_flags = SA_SIGINFO; 
    sa.sa_sigaction = sighandler;
    sigaction(SIGFPE, &sa, &old_sa);

    feenableexcept(FE_DIVBYZERO);
    printf("Dividing by zero..\n");
    a/=b;
    printf("Continuing\n");
}

私は 2 つのアプローチを取り(1)ました(2)。どちらも期待どおりに機能しません。

出力:

Dividing by zero..
Caught in handler, disabling
Floating point exception (core dumped)

期待される出力:

Dividing by zero..
Caught in handler, disabling
Continuing
4

1 に答える 1

6

計算が終了した後、浮動小数点例外が発生したかどうかを知りたいだけの場合は、オーバーヘッドが高いため、シグナルを使用しないでください。代わりに、通常の実行中にプロセッサによってすばやく設定される浮動小数点例外フラグを使用してください。

の C 標準を参照してください<fenv.h>。簡単に言うと:

  • #include <fenv.h>ソースファイルに挿入します。
  • #pragma STDC FENV_ACCESS on浮動小数点フラグにアクセスするか、デフォルト以外の浮動小数点モードで実行されるソース コードの前に挿入します。
  • #pragma STDC FENV_ACCESS off次のソース コードがフラグにアクセスしないか、デフォルト以外のモードで実行されない場合は、必要に応じて、上記のソース コードの後に​​挿入します。
  • 演算前に実行feclearexcept(FE_ALL_EXCEPT)してフラグをクリアします。
  • 計算後、実行fetestexcept(exceptions)してフラグをテストします。、、、、および/または、および場合によっては追加の実装定義フラグexceptionsのビットごとの OR である必要があります。FE_DIVBYZEROFE_INEXACTFE_INVALIDFE_OVERFLOWFE_UNDERFLOW

一部の C 実装では、浮動小数点環境へのアクセスが十分にサポートされていないことに注意してください。

于 2013-07-10T22:13:50.150 に答える