簡體   English   中英

為SIGFPE設置標志並繼續執行忽略FPE

[英]Set flag for SIGFPE and continue execution ignoring FPEs

在數值應用程序中,我想知道計算完成后是否發生浮點異常。 默認情況下,將以靜默方式忽略浮點除法和無效操作。

我的嘗試是啟用我關心的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");
}

我采用了兩種方法,第一種用(1)標記,第二種用(2)標記。 它們都沒有按預期工作。

輸出:

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

預期產出:

Dividing by zero..
Caught in handler, disabling
Continuing

如果您只是想知道,在計算完成后,是否發生了浮點異常,那么您不應該使用信號,因為它們的開銷很高。 而是使用浮點異常標志,這些標志在正常執行期間由處理器快速設置。

請參閱<fenv.h>上的C標准。 簡述:

  • 在源文件中插入#include <fenv.h>
  • 在任何可能訪問浮點標志或在非默認浮點模式下運行的源代碼之前插入#pragma STDC FENV_ACCESS on
  • 如果需要,請在上述源代碼之后插入#pragma STDC FENV_ACCESS off ,此時以下源代碼不訪問標志或在非默認模式下運行。
  • 在計算之前,執行feclearexcept(FE_ALL_EXCEPT)以清除標志。
  • 計算完成后,執行fetestexcept(exceptions)來測試標志。 exceptions應該是一個按位或的FE_DIVBYZEROFE_INEXACTFE_INVALIDFE_OVERFLOW ,和/或FE_UNDERFLOW ,以及可能的附加實現定義的標志。

請注意,某些C實現對訪問浮點環境的支持較差。

暫無
暫無

聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM