如果未明确定义任何过程接口,或者在Fortran 90+中的模块中,则抛出错误

时间:2014-05-26 15:11:53

标签: fortran fortran90

在文章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或其他编译器中是否有一个选项可以阻止编译?

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

2 个答案:

答案 0 :(得分:6)

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

  

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

这可以与-Werror结合使用,将其视为错误。

编译时(使用gfortran 4.8.2)

  call heffalump(1)
end

有人看到

  打电话给heffalump(1)
                     1
  警告:在(1)

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

当然,在大多数情况下,编译器无法判断该过程是否需要显式接口。有关允许编译器在这方面做一些额外工作的选项,请参阅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接口,另一个将开始抱怨接口已经定义且它们不同。 (来自战壕的实际故事。)