在混合C / Fortran代码中捕获浮点异常

时间:2013-07-04 14:54:28

标签: c++ fortran scientific-computing floating-point-exceptions

我很抱歉提出过多次问过的问题。但经过多次搜索,我意识到我可能对如何在C / C ++中处理FPE与在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中的异常处理还有另一种范例,我还没有完全掌握?

2 个答案:

答案 0 :(得分: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

答案 1 :(得分:0)

在下面的代码中,我将展示如何完全按照上面的问题进行操作。它依赖于提到的{OSMX扩展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);
}