【发布时间】:2018-06-17 17:03:55
【问题描述】:
我正在为一些 MPI 分散/收集例程使用一些现代 Fortran 包装器。我试图有一个包装器接口,它在输入上只有一个数组,并在输出上返回 MPI 操作的结果,对于几个派生类型,做这样的事情:
type(mytype), allocatable :: chunk(:),whole(:)
! [...] chunk descends from previous parts of the code
! Get global array
whole = gatherv(array=chunk,receiver_node=cpuid)
我正在使用返回 allocatable 数组的函数来执行此操作。但是,每当我返回未分配的结果时,gcc 6.2.0 和 gcc 7.1.0 都会出现分段错误。
我需要未分配结果的原因是有时我只需要在指定的 CPU 上收集整个数组,所以我不想在所有其他节点上浪费内存:接收节点返回一个分配的数组数据和所有其他节点接收到一个空且已释放的数组。
这是重现问题的示例代码:
program test_allocatable_fun
implicit none
integer, allocatable :: my_array(:)
integer :: n
n = 3; my_array = unallocated_array(n); print *, 'n=',n,' allocated(array)=',allocated(my_array)
n =-3; my_array = unallocated_array(n); print *, 'n=',n,' allocated(array)=',allocated(my_array)
n = 5; my_array = unallocated_array(n); print *, 'n=',n,' allocated(array)=',allocated(my_array)
n = 0; my_array = unallocated_array(n); print *, 'n=',n,' allocated(array)=',allocated(my_array)
return
contains
function unallocated_array(n) result(array)
integer, intent(in) :: n
integer, allocatable :: array(:)
integer :: j
if (n>0) then
allocate(array(n))
array(:) = [(j,j=1,n)]
else
if (allocated(array)) deallocate(array)
end if
end function unallocated_array
end program test_allocatable_fun
分段错误发生在赋值行,即:
my_array = unallocated_array(n)
你们之前有没有遇到过同样的问题?或者,我是否违反了标准中的任何内容?我不明白为什么应该强制返回可分配数组的函数分配返回值。是不是和在子程序中有一个intent(out) 虚拟变量一样?
【问题讨论】:
-
虽然我对此有更多思考,但为什么不将数组分配给
0size 呢?我怀疑这可能是正确的方法。这样你的代码就不需要一直检查返回数组的分配状态。 -
感谢@HighPerformanceMark 的评论 - 分配给 0 大小的数组可以解决问题。除了能够使用
size()内在函数之外,内存中未分配和 0 大小的已分配数组之间有什么区别? -
对于未分配的数组(或标量),除了测试其分配状态外,您几乎无能为力。正如您所发现的,如果您不确定是否分配了一个数组,那么每次您触摸它时,您都必须检查它的状态并处理不同代码路径上的两种返回可能性。分配到大小为 0 的数组几乎可以像任何其他已分配的数组一样处理。
标签: function fortran gfortran fortran2003 allocatable-array