Intel® Fortran Compiler
Build applications that can scale for the future with optimized code designed for Intel® Xeon® and compatible processors.

move_alloc and memory leak

velvia
Beginner
2,248 Views

Hi,It seems thatcall move_alloc(from, to)does not deallocate "to" if it is already allocated. It is a nice way to make memory leaks. I don't know what the Fortran standard has to say about it, but I don't see any reason why it should leak memory.I also realized that when "to" goes out of scope, is is not deallocated.Franois

0 Kudos
10 Replies
John4
Valued Contributor I
2,248 Views

Do you have any test code to support your comments? The following code works just as expected (and the amount of memory used is always the same):

[fortran]implicit none integer :: i
real, allocatable :: a(:), b(:) do i = 1, 10 print '(("ALLOCATED(", A, ")=", L1))', 'a', ALLOCATED(a), 'b', ALLOCATED(B) allocate (a(100), b(100)) a = 1 b = 2 call MOVE_ALLOC(a, b) print '(("ALLOCATED(", A, ")=", L1))', 'a', ALLOCATED(a), 'b', ALLOCATED(B) print '("b(1)=", G0)', b(1) call reset(b) read * enddo contains subroutine reset(x) real, allocatable, intent(OUT) :: x(:) end subroutine end[/fortran] The MOVE_ALLOC intrinsic is for ALLOCATABLE variables only ---which, by definition, DO NOT leak memory---. The deallocation of the "to" argument should occur, simply because it has INTENT(OUT); after that, the array descriptor from "from" is moved to "to", which means that on return the actual argument "to" is allocated and has the contents of the actual argument "from"... In simple terms, all MOVE_ALLOC does is changing the name of a variable.

The Fortran standard, does not specify implementation details, so I suppose the deallocation of an ALLOCATABLE variable that goes out of scope could be done asynchronously without any problem.

If you're using some memory debugging tool (e.g., valgrind), and your program does not rely heavily on pointers, just ignore the (false positive) messages regarding memory leaks.

0 Kudos
velvia
Beginner
2,248 Views
John,
I have some code to support my comments, but unfortunatly, I am not allowed to publish it. It is a 20,000 lines code that involve a lot of object-oriented Fortran. It involves only allocatable components, and no pointers.
If you run the program, you see with a unix "top" that the programs eats more and more memory. This phenomena almost goes away if I put a
deallocate(to)
call move_alloc(from, to)
instead of just the call move_alloc. Note that from and to are allocatable derived types with allocatable components.
Unfortunatly, the problem does not show up with some tests code. I will continue to work and find a test code where it leaks. Could you please confirm that it should be impossible to leak memory from a code that does not use any pointer variable ?
Francois
0 Kudos
IanH
Honored Contributor III
2,248 Views
Are any of your variables, or components of your variables, polymorphic? I know there are issues with those.
0 Kudos
Anonymous66
Valued Contributor I
2,248 Views
MOVE_ALLOC(from, to)should deallocate the "to" if it is already allocated. If it is not being deallocated, that is a bug.

We need to be able to reproduce the problem in order to investigate it though.

Could youshare the original program in a privateresponse orthough premier support? Only Intel employees will be able to see a response that has been marked private.

Thanks,
Annalee
0 Kudos
velvia
Beginner
2,248 Views
Hi.
I think, I've tracked it down. Here is a sample code that shows the bug.
[fortran]program main use cellStateArray_module, only : cellStateArray implicit none type(cellStateArray), allocatable :: myCellStateA, myCellStateB integer :: i, n integer :: nbLoops, k n = 1000000 nbLoops = 20000 allocate(myCellStateA) call myCellStateA%init(phi = [ (0.2, i = 1, n) ] ) do k = 1, nbLoops allocate(myCellStateB) call myCellStateB%initWithObject(myCellStateA) call move_alloc(from = myCellStateB, to = myCellStateA) end do end program main[/fortran]
[fortran]module cellStateArray_module implicit none private type, public :: cellStateArray private integer :: n_ real, allocatable, dimension(:) :: phi_ contains private procedure, public :: init procedure, public :: initWithObject end type cellStateArray contains subroutine init(this, phi) class(cellStateArray), intent(inout) :: this real, dimension(:), intent(in) :: phi this%n_ = size(phi) this%phi_ = phi end subroutine init subroutine initWithObject(this, that) class(cellStateArray), intent(inout) :: this class(cellStateArray), intent(in) :: that this%n_ = that%n_ this%phi_ = that%phi_ end subroutine initWithObject end module cellStateArray_module[/fortran]
I compile it with
ifort -assume realloc_lhs -c object.f90
ifort -assume realloc_lhs -c main.f90
ifort -assume realloc_lhs -o main object.o main.o
And you can see in a "top" that it leaks. What is interesting is that it does not leak if I remove the n_ instance variable.
Franois
0 Kudos
Anonymous66
Valued Contributor I
2,248 Views
Thanks for the reproducer. I have escalated this issue to the developers.

The issue number is DPD200180054.

I will post any updates I receive onthe issueto this thread.
0 Kudos
velvia
Beginner
2,248 Views
I found a temporary fix for the bug: move all allocatable members of the type at the beginning of the declaration. The memory leaks then disappears.
0 Kudos
Anonymous66
Valued Contributor I
2,248 Views

A fix has been found for this issue, we are planning to include it in the next major release which is scheduled for later this year.

0 Kudos
velvia
Beginner
2,248 Views
Thank you for working on it.
0 Kudos
Anonymous66
Valued Contributor I
2,248 Views
This is issue has been fixed in Intel® Fortran Composer XE for Linux* 2013 which is now available at the Intel® Registration Center. Regards, Annalee Intel Developer Support * Other names and brands may be claimed as the property of others.
0 Kudos
Reply