如果没有显式定义任何过程接口,或在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或其他编译器中是否有一个选项来防止编译,如果有一个调用其接口不是显式定义的过程(或在模块中定义)?

如果不是,它不应该是一个功能吗?

对于gfortran,有编译选项-Wimplicit-interface:

-Wimplicit-procedure
如果调用的过程既没有显式接口,也没有声明为EXTERNAL,则发出警告。

这可以与-Werror相结合,将此视为错误。

关于编译这个(使用gfortran 4.8.2)

  call heffalump(1)
end

看到

调用大象(1)
1
警告:在(1)

处使用隐式接口调用过程'heffalump'
但是,请注意,尽管这对于新开发的现代代码中的"愚蠢错误"可能是一个有用的测试,但事情可能非常正确,但仍然无法通过此测试。参见Vladimir F对这个答案的评论。

当然,编译器在大多数情况下无法判断过程是否需要显式接口。

是的,编译器有这个功能。如果fort有-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库版本声明了必需的接口,另一个MPI库版本就会开始抱怨接口已经定义并且它们不同。(来自战壕的真实故事)

最新更新