我是Fortran编程的新手,我试图理解子程序之间的调用。所以我写了一个简单的程序来测试它
这是我的代码
program dummy
real, allocatable, dimension(:) :: zz,yy
call test2(zz,yy)
print *, zz, yy
contains
subroutine test1(ar1,ar2,arsum)
real, dimension(:) :: ar1,ar2
real, allocatable, dimension(:) :: arsum
allocate(arsum(size(ar1)+size(ar2)))
arsum(1:size(ar1)) = ar1
arsum(size(ar1)+1:size(ar1)+size(ar2)) = ar2
end subroutine test1
subroutine test2(sg1,sg2)
real, dimension(3) :: g1,g3
real, dimension(4) :: g2,g4
real, allocatable,dimension(:) :: sg1,sg2,dum
g1 = 1.0
g2 = 2.0
g3 = 3.0
g4 = 4.0
call test1(g1,g3,dum)
sg1 = 2*dum
call test1(g2,g4,dum)
sg2 = 3*dum
end subroutine test2
end program dummy
然而,这会引发以下错误
forrtl: severe (151): allocatable array is already allocated
Image PC Routine Line Source
dummy.exe 0000000000409B1C Unknown Unknown Unknown
dummy.exe 0000000000402E70 MAIN__ 26 dummy.f90
dummy.exe 0000000000402A2E Unknown Unknown Unknown
libc-2.23.so 00002B3E716C7830 __libc_start_main Unknown Unknown
dummy.exe 0000000000402929 Unknown Unknown Unknown
test1
子例程简单地连接任何两个给定的数组。 Test2
子例程定义要连接的数组,并在输出上执行一些代数并将它们存储在新数组中。程序dummy
只是打印新数组。
我在这里做错了什么?
答案 0 :(得分:3)
让我们来看看这个程序的流程。这里涉及一些术语,但有希望通过其他文档探讨使用的内容。
主程序使用几个参数调用子例程test2
。对于这里的问题,这些论点没有意义。相反,请查看本地(到子例程)变量dum
。
dum
是一个可分配的数组。它在执行test2
时开始,因为未分配。它是test1
调用的第一个(实际)参数,后来是另一个test1
调用的(实际)参数。那么,出了什么问题?
这里的论点意图至关重要。真的很关键。在继续这个答案之前,应该先阅读其他地方的意图。
所以,我们现在熟悉论证意图。
在输入子例程test1
时,伪参数arsum
具有与实际参数dum
相同的分配状态。在test1
执行期间,有一个allocate
声明。
allocate
语句只能尝试分配尚未分配的内容。这在第一次调用时没问题:未分配条目dum
/ arsum
。在执行子例程arsum
的过程中,这会影响test2
dum
的分配状态。
现在已分配对test1
arsum
的第二次调用,因为已分配实际参数dum
。由于此原因,allocate
语句失败,并显示错误消息。
那是问题所在;怎么修?我们需要确保未分配arsum
。有两种显而易见的方法:
arsum
的分配状态并做出相应的回应(可能是deallocate
); dum
。test1
但是可能有更合适的方式。请注意,dum
仅在返回test2
某些操作的值时才有用。回想一下意图:这是intent(out)
表示的意思。
如果我们将子例程test1
重写为
subroutine test1(ar1,ar2,arsum)
real, dimension(:) :: ar1,ar2
real, allocatable, dimension(:), intent(out) :: arsum
allocate(arsum(size(ar1)+size(ar2)))
arsum(1:size(ar1)) = ar1
arsum(size(ar1)+1:size(ar1)+size(ar2)) = ar2
end subroutine test1
然后,由于intent(out)
,属性arsum
/ dum
会在录入时自动解除分配。
最后(并且未显示),人们甚至可以考虑使用函数返回arsum
甚至使用自动数组而不是可分配数组。或者,甚至Fortran 2003自动分配和数组构造函数:
subroutine test1(ar1,ar2,arsum)
real, dimension(:) :: ar1,ar2
real, allocatable, dimension(:) :: arsum ! Or with `intent(out)`
arsum = [ar1,ar2]
end subroutine test1