Interface 使用隐式接口调用外部过程的模块
以下代码组合了模块过程和外部过程:Interface 使用隐式接口调用外部过程的模块,interface,module,fortran90,subroutine,Interface,Module,Fortran90,Subroutine,以下代码组合了模块过程和外部过程: module module_dummy implicit none contains subroutine foo(a) real, intent(inout) :: a(:) call bar(a) end subroutine foo end module module_dummy program main use module_dummy implicit none integer, par
module module_dummy
implicit none
contains
subroutine foo(a)
real, intent(inout) :: a(:)
call bar(a)
end subroutine foo
end module module_dummy
program main
use module_dummy
implicit none
integer, parameter :: nelems = 100000000
real, allocatable :: a(:)
allocate( a(nelems) )
a = 0.0
call foo(a)
print *, a(1:10)
deallocate(a)
end program main
subroutine bar(a)
implicit none
real, intent(inout) :: a(:)
a = 1.0
end subroutine bar
似乎失败了:
分段故障
0.000
而不是一块1.000
bar
的隐式接口声明有关,事实上,可以通过任何方式添加显式接口来解决该问题,例如使用:
module module_dummy
implicit none
contains
subroutine foo(a)
interface
subroutine bar(x)
real, intent(inout) :: x(:)
end subroutine bar
end interface
real, intent(inout) :: a(:)
call bar(a)
end subroutine foo
end module module_dummy
或者在模块内声明条形图
,以供模块\u dummy
使用
不管怎样,我真的不明白一开始的错误是什么。我在(第12.3.2.4节)上发现:
过程的伪参数的类型、类型参数和形状
引用自程序接口所在的范围界定单元
隐式必须使实际参数与
伪参数的特征
在这种情况下,规则似乎得到了遵守,因为a
始终声明为
real, intent(inout) :: a(:)
那么,我在解释导致前面代码错误的标准时遗漏了什么呢?假定形状的伪参数必须在其引用点有一个明确的接口。F90 12.3.1.1第2c项
实际上,假定的形状数组是通过传递描述符来传递的,描述符是一种描述数组的边界和存储位置的小结构。Ye olde F77显式形状和假定大小数组仅通过传递第一个元素的地址来传递。如果没有显式接口,编译器就不知道它需要构建和传递描述符,从而导致混乱和混乱。你知道为什么大多数编译器(如GNU、英特尔)都需要这样做吗默认情况下,不要在
-Wall
捆绑包或应强制执行f90标准的选项中包含此特定检查?/warn:对于英特尔编译器,所有选项都包含此检查。但是编译器在看到引用之前必须先看到子例程的定义。在代码中,带有子例程的程序单元遵循引用(如果再次编译文件,可能会看到错误)。在一般情况下,对过程的引用可能在另一台机器上的单独文件中,可能在子程序本身之前编译!很难报告如此“遥远”的错误。只想在这里加上我的两分钱。几个月前我遇到了同样的问题。伊恩的答案是正确的,正如你们现在所知道的,还有他引用的F90标准。让我抓狂的是,我没有看到一本教科书,甚至没有一个网站来讨论这个问题。有很多例子是以您希望的方式在接口和模块内部传递数组的,但我找不到任何声明,大意是必须这样做。。。。在F90标准之外。好奇。令人沮丧的是,不同的人通过不同的途径学习该语言的各个方面,但就我所关注的论坛而言,我敢说它几乎是一个常见问题(也许一个经常遇到的问题是更好的术语?)。我在两篇Fortran文本(现代Fortran解释+Fortran 2003手册,后者可能不是最明显/最合适的地方)和我的主要编译器文档中提到了它。最安全的方法是始终确保在使用任何F90功能时提供明确的接口,或者更好的方法是,尽可能始终使用模块。