Выдача ошибки, если какой-либо интерфейс процедуры не определен явно, или в модуле в Fortran 90+
в статье ошибки в программах Fortran 90, которые могут вас удивить
есть следующий раздел,
опасность вызова процедур стиля Fortran 90
program main real, dimension(5) :: x x = 0. ! THIS IS WRONG call incb(x) print *, x end program main subroutine incb(a) ! this is a fortran90 style subroutine real, dimension(:) :: a a = a + 1. end subroutine incb
объяснение подпрограмма incb использует предполагаемую форму стиля Fortran 90 массив (содержащий размер(:)). Такие процедуры должны быть в модуль, или иметь явный интерфейс везде, где они используются. В этом образец, ни одна правда.
одним из правильных способов вызова таких процедур является использование явного интерфейс следующим образом:
program main real, dimension(5) :: x ! THIS IS THE RIGHT WAY interface subroutine incb(a) real, dimension(:) :: a end subroutine incb end interface x = 0. call incb(x) print *, x end program main subroutine incb(a) ! this is a fortran90 style subroutine real, dimension(:) :: a a = a + 1. end subroutine incb
если подпрограмма находится в модуле, интерфейсы генерируются автоматически и не нужно явно писать.
! THIS IS ANOTHER RIGHT WAY module inc contains subroutine incb(a) ! this is a fortran90 style subroutine real, dimension(:) :: a a = a + 1. end subroutine incb end module inc program main use inc real, dimension(5) :: x x = 0. call incb(x) print *, x end program main
если используются интерфейсы, интерфейс должен соответствовать фактической функции.
Итак, продолжая мой вопрос, есть ли вариант в gfortran
или другие компиляторы для предотвращения компиляция если есть вызов процедуры, интерфейс которой не определен explicity (или определен в модуле)?
если нет, то разве это не должно быть функцией?
2 ответов
для gfortran есть опция компиляции -Wimplicit-interface
:
- Wimplicit-процедура
Предупредите, если вызывается процедура, которая не имеет явного интерфейса и не объявлена как внешняя.
Это может быть связано с -Werror
рассматривать это как ошибку.
при компиляции этого (с gfortran 4.8.2)
call heffalump(1)
end
видит
вызовите heffalump (1)
1
Предупреждение: процедура 'heffalump' вызывается с неявным интерфейсом в (1)
обратите внимание, однако, что, хотя это может быть полезным тестом для "глупых ошибок" в недавно разработанном современном коде, все может быть совершенно правильно и все равно провалить этот тест. См. также комментарий Владимира Ф К этому ответу.
конечно, компилятор в большинстве случаев не может сказать, требует ли процедура явного интерфейса. См.ответ для опций, позволяющих компилятор сделать немного дополнительную работу в этом отношении.
Да, у компиляторов есть это. Ифорт имеет -warn interfaces
, входящего в -warn
, gfortran имеет эту регистрацию -Wall
.
interf.f90:6.15:
call incb(x)
1
Error: Procedure 'incb' at (1) with assumed-shape dummy argument 'a' must have an explicit interface
у компилятора будет проблема с проверкой этого, если они находятся в разных файлах. Кто-то найдет, кто-то нет.
> gfortran incb.f90 interf.f90 -Wall
> ifort incb.f90 interf.f90 -warn
interf.f90(6): error #7978: Required interface for passing assumed shape array is missing from original source [X]
call incb(x)
----------------^
compilation aborted for interf.f90 (code 1)
как пишет @francesalus, вы можете заставить предупреждения для неявных интерфейсов -Wimplicit-interface
. Это, однако, делает что-то другое. Он предупреждает для процедура с неявным интерфейсом, даже когда она стандарт соответствует его.
если вы соедините его с -Werror
вам нужно будет написать интерфейс для каждой процедуры MPI, которая работает с буферами, для каждой используемой устаревшей библиотеки. Я использую его, но мой код строго в модулях, и мне действительно пришлось писать интерфейсы для каждой процедуры MPI, которую я использую, которая отправляет или получает некоторый буфер. Для каждого типа буфера вам нужен отдельный интерфейс (по крайней мере, в текущем Fortran 2008).
еще хуже, некоторые MPI реализации предоставляют явные интерфейсы для определенных процедур, а некоторые нет. Как только вы попытаетесь объявить требуемые интерфейсы для одной версии библиотеки MPI, другой начнет жаловаться, что интерфейс уже определен, и они отличаются. (Реальная история из окопов.)