Bug 51160 - [OOP] Memory leak with abstract type
Summary: [OOP] Memory leak with abstract type
Status: RESOLVED FIXED
Alias: None
Product: gcc
Classification: Unclassified
Component: fortran (show other bugs)
Version: 4.7.0
: P3 normal
Target Milestone: ---
Assignee: Not yet assigned to anyone
URL:
Keywords: wrong-code
Depends on:
Blocks:
 
Reported: 2011-11-16 14:18 UTC by mrestelli
Modified: 2013-08-08 15:04 UTC (History)
1 user (show)

See Also:
Host:
Target:
Build:
Known to work:
Known to fail:
Last reconfirmed:


Attachments

Note You need to log in before you can comment on or make changes to this bug.
Description mrestelli 2011-11-16 14:18:50 UTC
Hi,
   the attached code, which I think is correct, leaks memory.
According to valgrind this happens in subroutine subr, at line

  class(et), intent(inout) :: y

Here is the output:

==29006== HEAP SUMMARY:
==29006==     in use at exit: 40,000 bytes in 100 blocks
==29006==   total heap usage: 223 allocs, 123 frees, 57,583 bytes allocated
==29006== 
==29006== 40,000 bytes in 100 blocks are definitely lost in loss record 1 of 1
==29006==    at 0x4C26F5D: malloc (vg_replace_malloc.c:263)
==29006==    by 0x400A20: __mod2_MOD___copy_mod2_Et (test.f90:38)
==29006==    by 0x4008E6: __mod1_MOD_sub (test.f90:24)
==29006==    by 0x400D0C: MAIN__ (test.f90:53)
==29006==    by 0x400E1E: main (test.f90:46)
==29006== 
==29006== LEAK SUMMARY:
==29006==    definitely lost: 40,000 bytes in 100 blocks
==29006==    indirectly lost: 0 bytes in 0 blocks
==29006==      possibly lost: 0 bytes in 0 blocks
==29006==    still reachable: 0 bytes in 0 blocks
==29006==         suppressed: 0 bytes in 0 blocks
==29006== 

The problem becomes more and more severe increasing n.

gfortran --version
GNU Fortran (GCC) 4.7.0 20111116 (experimental)

and I'm compiling with
gfortran -g test.f90 -o prg



module mod1
implicit none
 type, abstract :: at
  contains
  procedure(i_copy), deferred, pass(y) :: copy
 end type at
 abstract interface
  subroutine i_copy(y,x)
   import :: at
   implicit none
   class(at), intent(in)    :: x
   class(at), intent(inout) :: y
  end subroutine i_copy
 end interface
contains
 subroutine sub(q,p)
  class(at), intent(in) :: p
  class(at), intent(inout) :: q
  class(at), allocatable :: r
   allocate(r,source=p)
   call r%copy(p)
   call q%copy(r)
   deallocate(r)
 end subroutine sub
end module mod1

module mod2
 use mod1
implicit none
 type, extends(at) :: et
  real, allocatable :: u(:)
 contains
  procedure, pass(y) :: copy => subr
 end type et
contains
 subroutine subr(y,x)
  class(at), intent(in)    :: x
  class(et), intent(inout) :: y
   select type(x); type is(et)
    y%u = x%u
   end select
 end subroutine subr
end module mod2

program prog
 use mod1
 use mod2
 integer, parameter :: n = 100
 type(et) :: a, b
 allocate(a%u(n)); a%u = 1.5
 allocate(b%u(n))
 do i=1,n
   call sub(b,a)
 enddo
 deallocate(a%u,b%u)
end program prog
Comment 1 Tobias Burnus 2011-11-16 15:41:41 UTC
I think your issue has nothing to do with abstract types but rather with working with polymorphic data ("CLASS").

I think the issue is that "r"'s "u" component in "sub" is not freed at the end, which would be a duplicate of PR 46321.
Comment 2 janus 2013-08-08 15:04:25 UTC
(In reply to Tobias Burnus from comment #1)
> I think your issue has nothing to do with abstract types but rather with
> working with polymorphic data ("CLASS").
> 
> I think the issue is that "r"'s "u" component in "sub" is not freed at the
> end, which would be a duplicate of PR 46321.

Correct. And now that polymorphic deallocation is implemented, also the memory leak is gone: The dump shows that the _final procedure is called, and also valgrind reports a clean memory footprint:

==5457== HEAP SUMMARY:
==5457==     in use at exit: 0 bytes in 0 blocks
==5457==   total heap usage: 423 allocs, 423 frees, 58,341 bytes allocated
==5457== 
==5457== All heap blocks were freed -- no leaks are possible