Перехват ошибок и сигналов времени выполнения Fortran в привязке C ++ - PullRequest
3 голосов
/ 09 июня 2019

Я хотел бы иметь возможность отлавливать завершающие ошибки времени исполнения Fortran в привязке C ++. У меня есть устаревший код F90, к которому можно привязать и ожидать всевозможные ошибки, например числовой, IO и т. д.

Мне удалось справиться со STOP согласно: Перехват Fortran STOP из C ++ и может генерировать / ловить исключение для этого случая в коде C ++.

Я получил некоторое понимание «Обработка сигналов в Фортране» в https://www.sharcnet.ca/help/images/4/42/Fortran_Signal_Handling.pdf

Однако я не справляюсь с этим, пример для f90 fortran был бы очень полезен.

Например, попытка открыть несуществующий файл в подпрограмме fortran приведет к ошибке времени выполнения, и код C ++ завершится:

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

Ошибка выполнения Fortran: невозможно открыть файл 'fnameBAD': такого файла или каталога нет

Я бы хотел уметь распознавать эту и другие ошибки времени выполнения по сигналам.

Ответы [ 2 ]

2 голосов
/ 10 июня 2019

Это не сработает, по крайней мере, для GFortran. При сбое оператора OPEN библиотека времени выполнения GFortran отключается, и только в конце концов генерируется сигнал. Таким образом, к тому времени, когда вы можете перехватить сигнал в обработчике сигналов, libgfortran уже отключился (включая закрытие всех открытых файлов).

Решение, как говорит Владимир Ф в комментарии, состоит в том, чтобы отловить ошибку в операторе OPEN со спецификатором iostat=.

0 голосов
/ 10 июня 2019

Я реализовал нечто подобное для тестирования модулей C-bindings для кода Fortran из C / C ++ для перехвата abort вызовов с использованием setjmp и longjmp (по сути, так же, как ответ в ужесвязанный вопрос ):

#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, это не гарантирует, что все внутреннее состояниев Фортране библиотека времени выполнения восстановлена.

Фактически обе книги Современный Фортран: стиль и использование (правило 182) и Справочник Фортрана 2003 (15.6.4) отметим, что код на Фортране не следует заключать между setjmp и longjmp.

С другой стороны, существуют поставщики компиляторов, которые явно предоставляют setjmp / longjmp оболочки ( Oracle) например), а также несколько проектов с аналогичной направленностью:

Это, как говорится, вероятно, лучше (и болееТаблица) подход к использованию правильной обработки ошибок с использованием атрибута iostat, когда это возможно, как уже прокомментировали другие.

...