模块调用具有隐式接口的外部过程

Mas*_*ano 2 module interface subroutine fortran90

以下代码,结合模块程序外部程序

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
Run Code Online (Sandbox Code Playgroud)

似乎失败了:

  1. segmentation fault
  2. 打印块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
Run Code Online (Sandbox Code Playgroud)

bar在模块内部声明module_dummy.

无论如何,我真的不明白首先是什么错误。我在Fortran 90 标准(第 12.3.2.4 节)上发现的内容说:

从过程的接口是隐式的作用域单元引用的过程的类型、类型参数和虚拟参数的形状必须使得实际参数与虚拟参数的特征一致。

在这种情况下,规则似乎得到了尊重,因为a总是声明为

real, intent(inout) :: a(:) 
Run Code Online (Sandbox Code Playgroud)

那么,我在解释使先前代码出错的标准时遗漏了什么?

Ian*_*anH 5

假定形状的虚拟参数必须在其引用点具有显式接口。F90 12.3.1.1 第 2c 项。

实际上,假定的形状数组是通过传递一个描述符来传递的——一个描述数组的边界和存储位置的小结构。Ye-olde F77 显式形状和假定大小数组仅通过传递第一个元素的地址来传递。如果没有显式接口,编译器不知道它需要构建和传递描述符 - 因此会导致混乱和混乱。

  • 不同的人通过不同的途径学习语言的各个方面,但就我监控的论坛而言,我敢说它接近于常见问题解答(也许经常遇到的问题是更好的术语?)。在我拥有的两篇 Fortran 文本(Modern Fortran Explained + The Fortran 2003 Handbook,后者可能不是最明显/最合适的地方)和我的主要编译器的文档中都提到了这一点。最安全的方法是在使用任何 F90 功能时始终确保提供显式接口,或者更好的是,**始终** **尽可能使用** **模块**。 (2认同)