function returning array with no defined explicit

2019-07-23 22:30发布

I am wondering how to return an array from a function without any knowledge of the shape until runtime (including assumed shape arrays). I'll explain with examples. This works

module foo 
contains
   function getArray(:)
      real :: getArray(3)
      integer :: i
      do i=1,3
         getArray(i) = 10.0*i
      enddo
   end function

end module

program xx
   use foo 
   real :: array(3)
   integer :: i

   array = getArray()
   print *, array
end program

This also works, because it makes use of automatic arrays

module foo 
contains
   function getArray(length)
      integer :: length
      real :: getArray(length)
      integer :: i
      do i=1,length
         getArray(i) = 10.0*i
      enddo
   end function

end module

program xx
   use foo 
   real :: array(5)
   integer :: i

   array = getArray(5)
   print *, array
end program

What about this one? is it valid Fortran? do I have a memory leak in this case

module foo 
  contains
     function getArray()
        real, allocatable :: getArray(:)
        integer :: length
        integer :: i

        length = 5 ! coming, for example, from disk

        allocate(getArray(length))

        do i=1,length
            getArray(i) = 10.0*i
        enddo

        ! cannot call deallocate() or a crash occurs
     end function

end module

use foo 
  real :: array(5,5) ! get max size from other means, so to have enough space
  integer :: i

  array = getArray()
  ! leaking memory here ? unexpected behavior ?
end program

2条回答
狗以群分
2楼-- · 2019-07-23 22:51

This ability of a function to return an allocatable array is provided by TR 15581. See http://www.nag.co.uk/nagware/np/doc/tr.asp. The function must allocate the array and "The result of an allocatable array function is automatically deallocated after it has been used", i.e., no memory leak!

Also see the discussions at http://www.tek-tips.com/viewthread.cfm?qid=1613318&page=5 and http://software.intel.com/en-us/blogs/2008/03/31/doctor-it-hurts-when-i-do-this/.

Another new feature of Fortran 2003, when implemented, will allow you to change "real :: array(5,5)" to declaring "array" as an allocatable also, and it will be automatically allocated to the correct size upon assignment -- no need to pre-allocate it. Very easy! This is available in the late versions of Intel Fortran, but is not active by default. See the last link above.

查看更多
祖国的老花朵
3楼-- · 2019-07-23 23:07

If I compile this code:

(file bar.f90)

program bar

  use foo

  real :: array(5,5) ! get max size from other means, so to have enough space
  integer :: i

  array = getArray()
  ! leaking memory here ? unexpected behavior ?

end program

(file foo.f90)

module foo
  contains
     function getArray()
        real, allocatable :: getArray(:,:)
        integer :: length
        integer :: i

        length = 5 ! coming, for example, from disk

        allocate(getArray(length,length))

        do i=1,length
            getArray(i,:) = 10.0*i
        enddo

        ! cannot call deallocate() or a crash occurs
     end function

end module

using ifort -debug foo.f90 bar.f90

and let valgrind check the executable everything seems fine:

valgrind --tool=memcheck --leak-check=yes --show-reachable=yes --num-callers=20 ./a.out
==8019== Memcheck, a memory error detector
==8019== Copyright (C) 2002-2009, and GNU GPL'd, by Julian Seward et al.
==8019== Using Valgrind-3.6.0.SVN-Debian and LibVEX; rerun with -h for copyright info
==8019== Command: ./a.out
==8019==
==8019==
==8019== HEAP SUMMARY:
==8019==     in use at exit: 0 bytes in 0 blocks
==8019==   total heap usage: 2 allocs, 2 frees, 108 bytes allocated
==8019==
==8019== All heap blocks were freed -- no leaks are possible
==8019==
==8019== For counts of detected and suppressed errors, rerun with: -v
==8019== ERROR SUMMARY: 0 errors from 0 contexts (suppressed: 17 from 6)

Probably soon someone with far greater expertise will reply; I hope this'll do for the time being.

查看更多
登录 后发表回答