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功能时提供明确的接口,或者更好的方法是,尽可能始终使用模块。