3

我希望能够在 C++ 绑定中捕获终止的 Fortran 运行时错误。我有一个旧的 F90 代码可以绑定并期待各种错误,例如数字、IO 等。

我设法根据以下内容处理 STOP: Intercepting Fortran STOP from C++ and able to throw/catch exception for this case in the C++ code。

我在 https://www.sharcnet.ca/help/images/4/42/Fortran_Signal_Handling.pdf对“Fortran 中的信号处理”有了一些了解

但是,我无法解决这个问题,f90 fortran 的示例将非常有帮助。

例如,尝试在 fortran 子例程中打开一个不存在的文件会产生运行时错误,并且 C++ 代码会终止:

打开 (unit=13,FILE="fnameBAD",status="old",action="read",position="rewind")

Fortran 运行时错误:无法打开文件“fnameBAD”:没有这样的文件或目录

我希望能够使用信号捕获这个和其他运行时错误。

4

2 回答 2

2

这行不通,至少对 GFortran 来说是这样。当 thenOPEN语句失败时,GFortran 运行时库将自行关闭,并且仅在最后生成信号。因此,当您可以在信号处理程序中捕获信号时,libgfortran 已经自行关闭(包括关闭所有打开的文件)。

正如 Vladimir F 在评论中所说,解决方案是使用说明符捕获OPEN语句中的错误iostat=

于 2019-06-10T12:50:26.453 回答
0

我已经实现了类似的东西,用于对来自 C/C++ 的 Fortran 代码的 C 绑定进行单元测试,以使用and捕获abort调用(基本上与已链接问题中的答案相同):setjmplongjmp

#include <setjmp.h>
#include <signal.h>

jmp_buf jmp_env;

void on_sigabrt(int signum)
{
    (void) signum; // silence "unused parameter" warning
    longjmp(jmp_env, 1);
}

void func()
{
    if (setjmp(jmp_env) == 0) {
        signal(SIGABRT, &on_sigabrt);
        /* YOUR CALLS HERE */
    } else {
        /* ERROR HANDLING GOES HERE */
    }
}

@janneb 已经描述的问题仍然存在:即使longjmp应该将堆栈恢复到 的点setjmp,它也不能保证 Fortran 运行时库中的所有内部状态都已恢复。

事实上,两本书Modern Fortran: Style and Usage (rule 182) 和The Fortran 2003 Handbook (15.6.4) 都提到 Fortran 代码不应该包含在setjmp和之间longjmp

另一方面,有些编译器供应商明确提供setjmp/longjmp包装器(例如Oracle),以及几个具有类似重点的项目:

iostat话虽如此,正如其他人已经评论的那样,尽可能使用属性使用正确的错误处理可能是一种更好(且更便携)的方法。

于 2019-06-10T14:25:21.407 回答