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
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.
If I compile this code:
(file bar.f90)
(file foo.f90)
using
ifort -debug foo.f90 bar.f90
and let valgrind check the executable everything seems fine:
Probably soon someone with far greater expertise will reply; I hope this'll do for the time being.