PGIF90 fails to deallocate allocatable array on return

I have tracked down a severe memory leak in our large
Fortran electronic structure code, and the fault appears
to be that pgf90 is failing to deallocate an array on
subroutine exit as demanded by Fortran 95. The
array inquestion is declared as

real(kind=8), allocatable, dimension(:,:) :: arr

within a subroutine inside a module. It is allocated
conditionally depending on the vaues of various
subroutine arguments. The Fortran 95 standard requires
that this array be automatically deallocated upon exit
from the subroutine.

I am sure that the pgf90-generated code is simply failing to issue a deallocate for this array at subroutine exit. My evidence is that.

a) Using the google perftools heap profiler narrows the allocated
memory down to this particular subroutine, ans shows a mismatch
in allocates/deallocates.
b) If I add an explicit DEALLOCATE statement and recompile the
memory leak disappears and the process memory size does
not increase.
c) Even with the memory leak present the correct results are
calculated.

My attempts to boil this down to a simple test case have failed to
reproduce the problem. In my attempts to make a simple test case
arrays are automatically deallocated on exit as they should be.

I don’t know how to take this any further. The code is far too complex
and so far from being self contained that it would be useless as a
bug report. The problem happens at any optimisation level, even -O0
so I don’t think it can be an optimiser code path issue. Clearly something in the larger code is interfering with the automatic deallocation, but I can not see what this could be.

Has anyone else seen any similar behaviour? And any suggestions for
testcases are welcome.

Keith Refson

Hi Keith,

Can you please send a report to trs@pgroup.com?

It’s very possible that this is a compiler bug but without the code it’s very difficult to determine the true cause. Can the full source be made available? If not, can you send the resulting assembly files (add “-Mkeepasm -Manno”) of the problem source file, with and without the deallocate? While it’s much more difficult, we can sometimes determine the cause of such errors from the assembly source.

Also, which version of the compilers and OS are you using?

Thanks,
Mat

Thanks for the suggestion about looking at the assembler. Based on that
and my “failed” testcase which did deallocate I saw that it was possible
toidentify an explicit call fo “pgf90_dealloc” in the assembler near the
return. This was indeed missing in the real case. Because generating
assembler requires only a compile step and no link I was able to cut the
problem case from several hundred thousand lines to just…

module modtwo
contains
  subroutine subone(nk)
    integer,                               intent(in) :: nk
    integer, dimension(:), allocatable :: drst
    allocate(drst(100))
    return
   end subroutine subone
end module modtwo

When compiled at -O0 the assembler contains the calls:

$ egrep "call.*pgf90_(de)?alloc" ion-strip.s
        call    pgf90_alloc
        call    pgf90_allocated
        call    pgf90_dealloc

but at -O1

$ egrep "call.*pgf90_(de)?alloc" ion-strip.s
        call    pgf90_alloc

I worry a little that this is so oversimplified a case that the array
could be optimised away. But in that case why does the allocation
call remain. And I am reassured by the obvious concocted case that
this change of behaviour on change of optimisation level is somehow
specific to the example above. Though I can’t for the life of me figure
out what the difference which causes the differing behaviour is.

This is with 6.1-6 under 32-bit linux, but I see exactly the same behaviour
on 64-bit. I’ll also post to the support mailbox.

Keith Refson