I think I found a major pgi fortran memory leak bug:
I was trying to test the following code (adapted from allocatable function results example at: http://www.nag.co.uk/nagware/np/doc/tr.asp)
module array_mod contains function allocate_a(i) integer, allocatable, dimension(:) :: allocate_a integer :: i allocate(allocate_a(i)) allocate_a = 1 end function end module program test use array_mod integer, allocatable, dimension(:) :: x allocate(x(10)) x = allocate_a(10) print *,x deallocate(x) end
The output of this program is
1 1 1 1 1 1 1 1 1 1
When I try to run it with valgrind however, the output is:
... total heap usage: 6 allocs, 2 frees, ... ...
Indicating 4 unfreed memory blocks (from which 3 are still reachable, 1 is lost).
According to what I found, allocatable function results should be supported from the TR15581 extension. Why does valgrind report memory leaks?
gfortran doesn’t even compile this code, so I cannot test what valgrind reports then.
Is this normal behavior or is this due to valgrind?
Aren’t automatic allocated arrays automatically unallocated after being used at subroutine exits (unless save is specified)?
Aren’t they automatically unallocated at function exits?
For the sake of completeness, my end goal is to make a module with a function which returns an array from which we don’t know the size until runtime. I want to do this with convenience for the user, meaning the following:
- The user doesn’t have to declare the dimensions of the array containing the function results in the main program.
- The user doesn’t have to deallocate anything. It should be done automatically. Just call the function, that’s it!
- The function should be callable several times in the same main program.
- The program also has to be compatible with gfortran.
My solution: An implementation with pure pointers (although the second requirement is not met):
module array_mod contains function allocate_a_(x,k) implicit none integer :: x(:) integer, dimension(:,:), pointer :: allocate_a_ integer :: k, n integer :: i, j, counter nullify(allocate_a_) n = size(x) if (n .eq. k) then allocate(allocate_a_(k,1)) allocate_a_(:,1) = x else allocate(allocate_a_(k,n)) allocate_a_(:,1) = x(1:k) allocate_a_(:,2:) = reshape((/ (x(1:k)+i,i=1,n-1) /),(/k,n-1/)) endif end function end module program test use array_mod implicit none integer x(5) data x /1, 2, 3, 4, 5/ integer, pointer :: f_(:,:) f_ => allocate_a_(x,5) print *,f_ deallocate(f_) f_ => allocate_a_(x,3) print *,f_ deallocate(f_) end
The output is correct:
1 2 3 4 5 1 2 3 2 3 4 3 4 5 4 5 6 5 6 7
When running valgrind on the gfortran compiled version, 14 allocks and frees are detected. With the pgi fortran version, 33 allocks and 27 frees ==> memory leaks
How can this problem be solved? Why is there a leak?
Any ideas would help tremendously!
keywords: TR15581, allocatable, memory leak, valgrind, heap, lost blocks, function result, dynamic arrays, array pointers