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

如果未明确定义任何过程接口,或在Fortran 90+中的模块中,则引发错误;,fortran,fortran90,Fortran,Fortran90,文中 下面有一节, 调用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, dime

文中

下面有一节,

调用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
或其他编译器中有防止编译的选项


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

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

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

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

这可以与
-Werror
结合起来,将其视为错误

在编译时(使用gfortran 4.8.2)

人们看到

请致电Heffatlump(1)
1
警告:在(1)处使用隐式接口调用过程“heffalump”

但是,请注意,尽管这可能是对新开发的现代代码中的“愚蠢错误”的一个有用的测试,但事情可能是相当正确的,并且仍然无法通过此测试。另见Vladimir F对该答案的评论


当然,在大多数情况下,编译器无法判断过程是否需要显式接口。有关允许编译器在这方面做一些额外工作的选项,请参阅。

我发现gfortran特别需要以下两个标志:
-Wextra-Wimplicit interface
。你能把它们加到答案里吗?您还可以提到gfortran缺少C对应的一些标志功能,如
-Werror=implicit interface
不会产生任何结果,或者
-Wimplicit interface
本身会发出警告,但不会导致错误。我知道,但不能向您推荐,但我将描述它们。Fortran每天都变得越来越有趣。所以过程调用的隐式接口被认为是符合标准的,但不鼓励,对吗?这应该是因为向后兼容Fortran 77。尽管如此,对于像我这样的初学者来说,这些仍然是警告。我理解正确了吗?是的,主要是为了向后兼容。但如果不是这样,MPI将很难使用。只有使用扩展了Fortran 2008的新技术标准,这些用C编写的通用(或更好的无类型?)过程的显式接口才有可能实现。请小心,这检查得更多,并且可能会引入大量噪音。我使用它,但它对于许多旧程序来说是完全不可用的,这些程序使用许多合法的隐式过程或带有隐式接口的过程。尤其是-Werror,你会为许多完全符合标准的代码而疯狂。我完全同意:这是对这个问题的回答,但我真的不建议这样做。我想我会在答案中更加强调这一点,谢谢。不仅是因为愚蠢的错误,而且我认为这将变得至关重要,因为我正在对Fortran 77代码进行重构和现代化。我将使用假定的形状数组,这意味着隐式接口可以在任何地方导致内存泄漏。因此,没有松散的结局。您可以参考我前面的问题:@nrs现在我很难说
-Werror
,因为这会破坏您以增量方式进行重构的能力。如果您将问题从
如果…
阻止编译改为
如果…
警告,我将从我的答案中删掉这一部分,让大家都高兴。[我只是通过非常直白的方式说出来的。]我同意,但我认为这是一个需要解决的缺陷(或缺乏功能),除非
-Werror=*
的引入打破了任何人的工作流程。也许我可以在邮件列表中发布?我觉得这个问题应该保持原样,但如果你真的坚持,我可以改变。
  call heffalump(1)
end