2

對於提出以前多次提出的問題,我表示抱歉。但是經過多次搜索之後,我意識到我可能會在C/C++中處理FPE與在Fortran中處理它們的方式之間產生根本的誤解。在混合C/Fortran代碼中捕獲浮點異常

在Fortran(確切地說是GNU fortran)中,如果想捕獲一個浮點異常(例如使用NAN),編譯器標誌-ffpe-trap = invalid會執行這個技巧。一旦違規語句被執行,就會引發浮點異常。但是,在C(GNU gcc)中,似乎並不是這種情況。更令人討厭的是(但也許並不奇怪),相同的fortran代碼在從C main調用時不會引發異常(並暫停執行),而在Fortran主程序中調用時則會執行該代碼。這似乎與使用C或gfortran連接子無關。

經過大量的搜索和閱讀,我發現fenv.h中提供了C/C++功能,它提供了處理異常的「C方式」。我看到我可以設置異常標誌,然後檢查是否有異常。我可以看到這種方法如何在異常處理的方式上提供更多的靈活性。這是在C中處理異常的「最佳實踐」方式嗎?對於科學編程(其中C通常用於調用fortran代碼)似乎很不方便,必須先了解可能發生異常的位置。

C中有沒有(簡單的)方法讓代碼在第一次出現異常時暫停?或者在C語言中的異常處理方面還有另外一個範例,那就是我沒有完全掌握?

+0

我運行OS X. – Donna

+0

原來'feenableexcept()'是非標準。 [這個問題的答案](http://stackoverflow.com/questions/247053/enabling-floating-point-interrupts-on-mac-os-x-intel)有一些建議和[本博客文章](http: //philbull.wordpress.com/2012/12/09/update-floating-point-exception-handling-on-mac-os-x/)指向一些適用於Linux和Mac OS X的代碼。 –

+0

是的,我發現這篇文章和被引用的代碼似乎正是我所希望的。您是否對所描述的擴展是否合理? – Donna

回答

0

在下面的代碼,我將展示如何確實按照我上面提到的問題來做。它依賴於所提及的Mac OSX擴展here和描述的信號值 here

我不是這兩個主題的專家,所以不能聲稱這個代碼是多麼便攜。但它確實做了我想要的兩件事:它允許我將數據初始化爲「NAN」,並稍後捕獲這些未初始化值的無效使用。通過正常執行和gdb檢測到陷阱。

我當然會對這個解決方案有任何意見。


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

/* 
----------------------------------------------------------------------- 
This example illustrates how to initialize data with an sNAN. Later, if 
the data is used in its 'uninitialized' state, an exception is raised, 
and execution halts. 

The floating point exception handler 'fp_exception_glibc_extension' is 
needed for OS X portability. 

At least two blog posts were used in writing this : 

"Update: Floating-point exception handling on Mac OS X" 
http://philbull.wordpress.com/2012/12/09/update-floating-point-exception-handling-on-mac-os-x/ 
Note : there is a lengthy email exchange about how portable this extension is; see 
comments in the text of the code. 

"NaNs, Uninitialized Variables, and C++" 
http://codingcastles.blogspot.fr/2008/12/nans-in-c.html 
----------------------------------------------------------------------- 
*/ 

void set_snan(double& f) 
{ 
    *((long long*)&f) = 0x7ff0000000000001LL; 
} 

int main() 
{ 
    /* On OS X, this extension is provided by 
     'fp_exception_glibc_extension.{c,h} */ 
    feenableexcept(FE_INVALID); 

    double p; 
    set_snan(p); /* Initialize to signaling nan */ 

    double q; 
    q = 2*p;  /* Floating point exception is trapped here */ 
    printf("p = %f; q = %f\n",p,q); 
} 
+1

這裏需要使用'set_snan' 。在程序中稍後使用時,初始化math.h中提供的NAN宏的值不會被捕獲。 – Donna

1

既然你使用GNU工具,我會假設你在* nix上。您需要啓用浮點異常。完成後,使用信號傳遞異常。下面的代碼說明它:

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

void handler(int sig) { 
    printf("Floating Point Exception\n"); 
    exit(0); 
} 


int main(int argc, char ** argv) { 
    feenableexcept(FE_INVALID | FE_DIVBYZERO | FE_OVERFLOW | FE_UNDERFLOW); 
    signal(SIGFPE, handler); 

    float a = 42.0, b = 0.0, res; 

    res = a/b; 

    return 0; 
} 

鏈接鏈接libm:

gcc -o test test.c -lm 

在Windows上,我相信你需要使用結構化異常處理程序:http://msdn.microsoft.com/en-us/library/windows/desktop/ms680657(v=vs.85).aspx

+0

我正在運行OS X,其中feenableexcept不可用。但我剛剛遇到了這個擴展,事實證明我正是想做的。 [OSX_fpe_fix](http://philbull.wordpress.com/2012/12/09/update-floating-point-exception-handling-on-mac-os-x/) – Donna