问题描述
在下面的程序中,一个可分配的变量x
被传递给子程序test_sub
而没有被分配.在test_sub
中分配对应的可分配虚拟变量x_sub
:
In the following program, an allocatable variable x
is passed to a subroutine test_sub
without being allocated. The corresponding allocatable dummy variable x_sub
is allocated in 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
:
When control is returned to the main program, x
is allocated:
Before call to sub F
After call to sub T
如果test_sub
在分配x_sub
前返回,或者x_sub
在返回前被释放,则x
不被分配:
If test_sub
returns before allocating x_sub
, or if x_sub
is deallocated before returning, x
is not allocated:
Before call to sub F
After call to sub F
我使用 gfortran 4.4.7 和 ifort 19.0 观察到这种行为.
I observe this behavior using both gfortran 4.4.7 and ifort 19.0.
我的问题是这是否是标准行为.我本来希望在尝试传递 x
而不分配它时会出现段错误.我担心这种行为可能会导致大型程序出现意外结果.
My question is whether this is standard behavior. I would have expected to get a segfault when trying to pass x
without it being allocated. I'm worried this behavior might lead to unexpected results in larger programs.
推荐答案
您可以使用 intent
声明来控制例程中变量的分配行为:
You can use an intent
declaration to control the allocation behavior of your variable inside the routine:
real, allocatable, intent(inout) :: x(:)
等价于你的情况.
- 分配状态不是先验的,可以用
allocated(x)
进行测试; - 分配状态可以使用
allocate
/deallocate
改变
- Allocation status is not known a priori, it can be tested with
allocated(x)
; - Allocation status can change using
allocate
/deallocate
如果real, allocatable,intent(in) :: x(:)
,则分配状态不能在里面改变;
if real, allocatable, intent(in) :: x(:)
, then the allocation status cannot change inside of it;
- 可以使用
allocated(x)
测试分配状态 - 无法修改
如果 real, allocatable,intent(out) :: x(:)
,那么变量 x 总是初始化为非分配,不管它是什么调用例程之前的状态,因此您可以总是以 allocate(x(n))
开始您的子例程.
if real, allocatable, intent(out) :: x(:)
, then variable x is always initialized as non-allocated, regardless of its former status before calling the routine, so you can always begin your subroutine with allocate(x(n))
.
我相信您正在使用选项 1),但您想要 3).
I believe you're using option 1) but you want 3).
这篇关于将未分配的可分配变量作为可分配的虚拟参数传递的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持!