- Mark as New
- Bookmark
- Subscribe
- Mute
- Subscribe to RSS Feed
- Permalink
- Report Inappropriate Content
Hello!
The program below allocates a polymorphic derived type variable from a SOURCE expression in ALLOCATE statement. The SOURCE itself becomes allocated as a result of a function call with allocatable return type. This seemingly causes the allocation of the source's derived type components to get lost in a memory leak.
If you know what is going on here, I would appreciate your help!
[fortran]
module m
implicit none
type :: derived_type
! causes 8 bit memory leak per allocation
integer(8), allocatable :: alloc_comp ! (*)
end type
contains
! function with allocatable polymorphic result
function make_class()
class(derived_type), allocatable :: make_class ! (**)
allocate(make_class)
! this allocation apparently gets lost
allocate(make_class%alloc_comp)
end function
end module
program p
use m
implicit none
integer :: ii
! multiply leak by number of itterations
do ii = 1,10
call cause_mem_leak()
end do
contains
! assign allocatable polymorphic function result to local variable
subroutine cause_mem_leak()
class(derived_type), allocatable :: my_class
! source expression gets allocated inside the allocation statement
allocate(my_class, source = make_class())
! no help here:
deallocate(my_class%alloc_comp)
deallocate(my_class)
end subroutine
end program
[/fortran]
Results:
Valgrind detects 80 bit memory leak on my unix 64 bit Intel® Core™2 Quad CPU Q9400 @ 2.66GHz × 4 system.
Variations:
- (*) change to pointer here, and everything is fine.
- (**) change to type here and get a runtime crash:
"forrtl: severe (153): allocatable array or pointer is not allocated" - However, both changes made simultaneously bring back the leak again.
- Also, changing all 'class' into 'type' (e.g. pre-F2003 standard) solves all problems.
My Question:
Allocating the SOURCE expression inside an ALLOCATE statement. The intel docs say:
"If [..] source-expr is specified, it must not be allocated in the ALLOCATE statement in which it appears"
The expression 'make_class()', which triggers the allocation of the SOURCE, is part of the ALLOCATE statement.
However, the actual allocation of the SOURCE is done by second, nested ALLOCATE statement inside the 'make_class()' function.
Does that still make the code invalid?
If so, what is the Fortran way to assign an allocatable polymorphic function result to a variable?
(Without the "realloc-lhs in assignment to polymorphic" F2008 feature)?
Thank you, with regards
Ferdinand
Link Copied
- Mark as New
- Bookmark
- Subscribe
- Mute
- Subscribe to RSS Feed
- Permalink
- Report Inappropriate Content
Regarding your last question, I have wondered the same thing, and put that question to the comp.lang.fortran newsgroup. You can see the thread here: https://groups.google.com/forum/#!searchin/comp.lang.fortran/zaak/comp.lang.fortran/i_4xy9RtJAU/EETjD4jZQe0J
It is my understanding that you either need to use defined assignment to wrap a sourced allocation to achieve this with a F2003 compiler, however, it may not be wise to do so with F2008 on the horizon. Users who read a sourced allocation directly are less likely to be confused once F2008 is common, including polymorphic realloc_lhs. Note that copy/assignment(=) cannot be type bound in order for this to work.
[fortran]
generic :: assignment(=) => copy
contains
subroutine copy(lhs,rhs)
CLASS(my_abstract), INTENT(OUT), ALLOCATABLE :: lhs
CLASS(my_abstract), INTENT(IN) :: rhs
ALLOCATE(lhs, SOURCE=rhs)
end subroutine [/fortran]
- Mark as New
- Bookmark
- Subscribe
- Mute
- Subscribe to RSS Feed
- Permalink
- Report Inappropriate Content
Hi Zaak,
thanks for pointing to your informative newsgroup thread! I share your opinion in that a sourced allocation should be prefered over a defined assignment (e.g. hiding the allocate statement behind a '=' sign, hence pure (& obscure!) cosmetic) until F2008 polymorphic realloc_lhs is supported.
However, I tested the defined assignment approach with my sample program, but valgrind still detects a memory leak (ifort 14.0.1).
[fortran]
module m
implicit none
type :: derived_type
! causes 8 bit memory leak per allocation
integer(8), allocatable :: alloc_comp ! (*)
end type
! NEW: defined assignment to emulate polymorphic realloc_lhs
interface assignment(=)
module procedure copy
end interface
contains
! function with allocatable polymorphic result
function make_class()
class(derived_type), allocatable :: make_class ! (**)
allocate(make_class)
! this allocation apparently gets lost
allocate(make_class%alloc_comp)
end function
! NEW: emulate polymorphic realloc_lhs
subroutine copy(lhs, rhs)
! both lhs and rhs can be polymorphic
class(derived_type), allocatable, intent(out) :: lhs
class(derived_type), intent(in) :: rhs
allocate(lhs, source = rhs)
end subroutine
end module
program p
use m
implicit none
integer :: ii
! multiply leak by number of itterations
do ii = 1,10
call cause_mem_leak()
end do
contains
! assign allocatable polymorphic function result to local variable
subroutine cause_mem_leak()
class(derived_type), allocatable :: my_class
! source expression gets allocated inside the allocation statement
! allocate(my_class, source = make_class())
! NEW: try it with the defined assignment
my_class = make_class()
! no help here:
deallocate(my_class%alloc_comp)
deallocate(my_class)
end subroutine
end program
! NEW: changes to original sample program
! RESULTS: unchanged, e.g. still 80 bit memory leak
[/fortran]
No compiler flags where used, and valgrind --tool=memcheck ./a.out says:
==4063== LEAK SUMMARY:
==4063== definitely lost: 80 bytes in 10 blocks
==4063== indirectly lost: 0 bytes in 0 blocks
==4063== possibly lost: 0 bytes in 0 blocks
==4063== still reachable: 32 bytes in 1 blocks
==4063== suppressed: 0 bytes in 0 blocks
Best reagrds,
Ferdinand
- Mark as New
- Bookmark
- Subscribe
- Mute
- Subscribe to RSS Feed
- Permalink
- Report Inappropriate Content
I'm not entirely sure whether or not your code is standards conforming, but I think it is. Hopefully someone with a more intimate understanding with the standards can take a look at it.
Thanks for sharing your results!

- Subscribe to RSS Feed
- Mark Topic as New
- Mark Topic as Read
- Float this Topic for Current User
- Bookmark
- Subscribe
- Printer Friendly Page