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