Warning: file_get_contents(/data/phpspider/zhask/data//catemap/5/fortran/2.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
Function Fortran函数返回未分配数组导致分段错误_Function_Fortran_Gfortran_Fortran2003_Allocatable Array - Fatal编程技术网

Function Fortran函数返回未分配数组导致分段错误

Function Fortran函数返回未分配数组导致分段错误,function,fortran,gfortran,fortran2003,allocatable-array,Function,Fortran,Gfortran,Fortran2003,Allocatable Array,我正在努力使用一些现代的Fortran包装来实现一些MPI分散/聚集例程。我正在尝试使用一个包装器接口,该接口在输入时只有一个数组,在输出时返回MPI操作的结果,对于几种派生类型,执行如下操作: type(mytype), allocatable :: chunk(:),whole(:) ! [...] chunk descends from previous parts of the code ! Get global array whole = gatherv(array=chunk,r

我正在努力使用一些现代的Fortran包装来实现一些MPI分散/聚集例程。我正在尝试使用一个包装器接口,该接口在输入时只有一个数组,在输出时返回MPI操作的结果,对于几种派生类型,执行如下操作:

type(mytype), allocatable :: chunk(:),whole(:)

! [...] chunk descends from previous parts of the code

! Get global array
whole = gatherv(array=chunk,receiver_node=cpuid)
我使用返回
可分配
数组的函数来实现这一点。然而,每当我返回未分配的结果时,
gcc6.2.0
gcc7.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)
伪变量相同?

函数结果与具有
intent(out)
属性的伪参数不同。这里有一个显著的不同之处,即当函数的执行终止时,必须始终定义非指针函数结果。Fortran 2008 12.6.2.2 p4对此进行了介绍

定义要分配的可分配函数结果(任何对象)是必要的,但还不够

在某种程度上,您可以考虑始终引用函数结果的方式(否则将不执行函数)。未定义的实际参数也可能不会被引用,但这种引用不会是“自动”的

如注释中所述,函数结果可能被分配为大小为零的数组。零大小的数组始终具有定义的值


您可以在中看到零大小数组和未分配数组的一些比较。

我怀疑主程序中的任何可分配数组都包含全局性质的数据。我通常把这些变量放在一个模块中。这样,该变量不需要传递,可以在主程序、子例程和/或函数中分配和释放

因为数组是唯一的返回值,所以我将其更改为一个子例程。这对你有什么作用?每个模块、程序、函数和子例程中都应包含“隐式无”

module fun
   implicit none
   integer, allocatable :: my_array(:)
end module fun

program test_allocatable_fun
   use fun
   implicit none

   integer :: n

   n = 3; call unallocated_array(n); print *, 'n=',n,' allocated(array)=',allocated(my_array)
   n =-3; call unallocated_array(n); print *, 'n=',n,' allocated(array)=',allocated(my_array)
   n = 5; call unallocated_array(n); print *, 'n=',n,' allocated(array)=',allocated(my_array)
   n = 0; call unallocated_array(n); print *, 'n=',n,' allocated(array)=',allocated(my_array)

   return

   contains

subroutine unallocated_array(n)

    use fun
    implicit none

    integer, intent(in) :: n
    integer :: j
    if (n>0) then
        allocate(my_array(n))
        my_array(:) = [(j,j=1,n)]
    else
        if (allocated(my_array)) deallocate(my_array)
    end if
end subroutine unallocated_array

end program test_allocatable_fun

在我对此进行更多思考的同时,为什么不将数组分配到
0
size?我想这可能是正确的选择。这样,您的代码就不需要一直检查返回数组的分配状态。感谢@HighPerformanceMark的注释-分配到0大小的数组解决了这个问题。除了能够使用
size()
内在特性之外,内存中未分配数组和0大小已分配数组之间的区别是什么?除了测试其分配状态之外,您对未分配数组(或标量)几乎无能为力。正如您所发现的,如果您不确定是否分配了一个数组,那么每次触摸它时,您都必须检查它的状态,并处理沿不同代码路径返回的两种可能性。Allocated-to-size-0数组可以像对待任何其他已分配数组一样进行处理。这并不能真正回答问题。不能对所有内容都使用全局变量。许多人认为全局变量是一个非常糟糕的设计决策,应该尽可能避免。