将未分配的可分配变量作为可分配的虚拟参数传递

Passing unallocated allocatable variable as an allocatable dummy argument

在下面的程序中,一个可分配变量 x 被传递给一个子程序 test_sub 而没有被分配。相应的可分配虚拟变量 x_sub 分配在 test_sub:

module test_mod

    implicit none

    contains

        subroutine test_sub(x_sub)

            implicit none
            real, allocatable :: x_sub(:)

          ! Execution !

!           return
            allocate(x_sub(1))
!           deallocate(x_sub)

        end subroutine test_sub

end module test_mod

program test

    use test_mod, only: test_sub
    implicit none
    real, allocatable :: x(:)

  ! Execution !

    print*, 'Before call to sub', allocated(x)
    call test_sub(x)
    print*, 'After call to sub', allocated(x)

end program test

当控制返回到主程序时,分配x

 Before call to sub F
 After call to sub T

如果test_sub returns在分配x_sub之前,或者如果x_sub在返回之前被释放,则x不分配:

 Before call to sub F
 After call to sub F

我使用 gfortran 4.4.7 和 ifort 19.0 观察到这种行为。

我的问题是这是否是标准行为。我本以为在尝试传递 x 而不分配它时会出现段错误。我担心这种行为可能会导致大型程序出现意外结果。

这是标准行为。 allocatable 的虚拟参数 没有暗示需要在输入或输出上分配变量 。这只是意味着该变量是可分配的,因此您可以将其视为该函数内部的可分配变量,例如隐式重新分配等。

要查明它是否是自动分配的,您应该在执行自己的 allocate 之前在子例程中打印它。没有进行自动分配。

将未分配的可分配对象传递给可分配的虚拟参数是完全没问题的。它作为“未分配”传递。

您可以使用 intent 声明来控制例程中变量的分配行为:

  1. real, allocatable, intent(inout) :: x(:) 等同于你的情况。

    • 分配状态先验未知,可以使用 allocated(x);
    • 进行测试
    • 分配状态可以使用 allocate/deallocate
    • 更改
  2. 如果real, allocatable, intent(in) :: x(:),则分配状态不能在里面改变;

    • 可以使用allocated(x)
    • 测试分配状态
    • 无法修改
  3. 如果 real, allocatable, intent(out) :: x(:),那么变量 x 总是 初始化为未分配的 ,无论它在调用例程之前的状态如何,所以你总是可以用allocate(x(n))开始你的子程序吗?

我相信您使用的是选项 1),但您想要选项 3)。