在文章Mistakes in Fortran 90 Programs That Might Surprise You
中有以下部分,
调用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样式的假定形状 数组(包含维度(:))。这样的例程必须在a中 模块,或在任何地方使用显式接口。在这 例如,两者都不是真的。
调用此类过程的一种正确方法是使用显式 界面如下:
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
或其他编译器中是否有一个选项可以阻止编译?
如果没有,不应该是一个功能吗?
答案 0 :(得分:6)
对于gfortran,有编译选项-Wimplicit-interface
:
-Wimplicit-过程
如果调用的过程既没有显式接口也没有声明为EXTERNAL,则发出警告。
这可以与-Werror
结合使用,将其视为错误。
编译时(使用gfortran 4.8.2)
call heffalump(1)
end
有人看到
打电话给heffalump(1)然而,请注意,尽管这对于新开发的现代代码中的“愚蠢错误”是一个有用的测试,但事情可能非常正确并且仍然无法通过此测试。另见Vladimir F对此答案的评论。
1
警告:在(1)处使用隐式接口调用过程'heffalump'
当然,在大多数情况下,编译器无法判断该过程是否需要显式接口。有关允许编译器在这方面做一些额外工作的选项,请参阅this answer。
答案 1 :(得分:4)
是编译器确实有这个。如果-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
发出警告。然而,这有所不同。它使用隐式接口警告 EVERY 过程,即使它符合标准也是如此。
如果将其与-Werror
连接,则必须为每个使用缓冲区的MPI过程编写一个接口,用于您使用的每个旧库。我使用它,但我的代码严格在模块中,我真的必须编写接口到我使用的每个MPI过程,发送或接收一些缓冲区。对于每种类型的缓冲区,您都需要单独的接口(至少在当前的Fortran 2008中)。
更糟糕的是,一些MPI实现为某些过程提供了显式接口,而有些则没有。一旦您努力为一个MPI库版本声明require接口,另一个将开始抱怨接口已经定义且它们不同。 (来自战壕的实际故事。)