Reputation: 4430
When I run the code below through either gfortran and Valgrind or ifort and Intel Inspector a memory leak is detected the first time the procedure set
is called for a object. The second time does not seem to cause any memory leaks though. Why is that?
module mymod
implicit none
type mytype
integer, pointer :: intArray(:) => null()
contains
procedure :: set
end type mytype
contains
subroutine set(this, intArray)
class(mytype), intent(inout) :: this
integer, intent(in) :: intArray(:)
integer n
n = size(intArray)
nullify(this%intArray)
allocate(this%intArray(n)) !line 20
this%intArray = intArray
end subroutine set
end module mymod
program main
use mymod !line 28
implicit none
type(mytype) :: myvar
call myvar%set((/1,2,3/)) !line 33
print *, myvar%intArray
call myvar%set((/9,8,7,6,5/))
print *, myvar%intArray
end program main
Valgrind reports the following memory leak:
==6669== 12 bytes in 1 blocks are definitely lost in loss record 1 of 2
==6669== at 0x402BB7A: malloc (in /usr/lib/valgrind/vgpreload_memcheck-x86-linux.so)
==6669== by 0x804886A: __mymod_MOD_set (main.f90:20)
==6669== by 0x8048988: MAIN__ (main.f90:33)
==6669== by 0x8048ADC: main (main.f90:28)
For line numbers, see the comments in the code.
Upvotes: 0
Views: 670
Reputation: 60008
The leak actually happens on the second call of set
. You nullify
the pointer, but it is already associated and the content is lost. So, you must call deallocate
before and test the association status with associated()
.
Upvotes: 2
Reputation: 21431
The first time the set binding is called you allocate an "anonymous" size three array to store the supplied integers. At the same time you associate the intArray
component to point at that newly allocated array - when you ALLOCATE pointers the statement is conceptually doing two things.
The second time the set binding is called you break the association between the intArray
component and the allocation with the NULLIFY statement, before you repeat the pointer allocation process.
Nullify does not (necessarily) deallocate. Your program has basically lost track of that initial allocation of a size three array. Three integers, typically four bytes per integer -- twelve bytes lost.
If you are using pointers, a general principle is that for every ALLOCATE encountered in your code path you need to have a matching DEALLOCATE in the later code path.
(In Fortran 2003 or later (which is what you are using, because you have type bound procedures), you should only be using pointers and pointer components if you are actually pointing them at things. If you are really just using the pointers as "values", then you should be using allocatable variables or components.)
Upvotes: 4