- Mark as New
- Bookmark
- Subscribe
- Mute
- Subscribe to RSS Feed
- Permalink
- Report Inappropriate Content
Caveat: My understanding of the F2003, F2008 allocatable function results and scalars as derived type components is a little bit hazy, but I am pretty sure that the following code is F2008 compliant. Please correct me, and tell my where I've run amuck if that is not the case. Here is a simple test program:
[fortran]
module stringbug
implicit none
private
public :: string_t
type :: string_t
private
character(:) ,allocatable :: string
contains
procedure :: ConcatChars
procedure :: Assign
procedure :: AssignChars
procedure :: Get
generic :: operator(//) => ConcatChars
generic :: assignment(=) => Assign ,AssignChars
end type
interface string_t
procedure :: StringConstructor
end interface
contains
function StringConstructor(string) result(res)
character(*) ,intent(in) :: string
type(string_t) :: res
! allocate(res)
res%string = string
end function
subroutine Assign(lhs,rhs)
class(string_t) ,intent(inout) :: lhs
class(string_t) ,intent(in) :: rhs
lhs%string = rhs%string
end subroutine
subroutine AssignChars(lhs,rhs)
class(string_t) ,intent(inout) :: lhs
character(*) ,intent(in) :: rhs
lhs%string = rhs
end subroutine
function ConcatChars(lhs,rhs) result(res)
class(string_t) ,intent(in) :: lhs
character(*) ,intent(in) :: rhs
class(string_t) ,allocatable :: res
allocate(res,mold=lhs)
res%string = lhs%string // rhs ! This leaks
end function
function Get(this) result(res)
class(string_t) ,intent(in) :: this
character(:) ,allocatable :: res
res = this%string
end function
end module
program memleak
use stringbug, only: string_t
implicit none
class(string_t) ,allocatable :: testvar
allocate(string_t :: testvar)
testvar = 'foobar'
testvar = string_t('mystring')
print*, testvar%Get()
testvar = testvar // 'baz' ! this leaks
testvar = testvar%ConcatChars('bip') ! this does too.
print*, testvar%Get()
end program
[/fortran]
The code generated by
[bash]
$ ifort -V
Intel(R) Fortran Intel(R) 64 Compiler XE for applications running on Intel(R) 64, Version 13.1.0.146 Build 20130121 [/bash]
seems to leak at line 41 in ConcatChars (which is being called via the overloaded operator //)
The code was compiled as:
[bash]$ ifort -g -O0 -assume realloc_lhs -o memleak bug.f90[/bash] on a RHEL 5 x86_64 machine and the leak was found via [bash]$ valgrind --leak-check ./memleak[/bash] The valgrind output is attached.
I think this might be a compiler bug.
Thanks,
Link Copied
- Mark as New
- Bookmark
- Subscribe
- Mute
- Subscribe to RSS Feed
- Permalink
- Report Inappropriate Content
I think Steve Lionel might be able to recall a similar issue where a temporary was created on the right side in A = B + C, or was it A = fn(B + C). I think the issue was the array temporary was not reclaimed.
Jim Dempsey
- Mark as New
- Bookmark
- Subscribe
- Mute
- Subscribe to RSS Feed
- Permalink
- Report Inappropriate Content
I can reproduce this and have escalated it to the developers as issue DPD200244704. Thanks for reporting it.
- Mark as New
- Bookmark
- Subscribe
- Mute
- Subscribe to RSS Feed
- Permalink
- Report Inappropriate Content
jimdempseyatthecove wrote:
I think Steve Lionel might be able to recall a similar issue where a temporary was created on the right side in A = B + C, or was it A = fn(B + C). I think the issue was the array temporary was not reclaimed.
Jim Dempsey
Jim and Steve,
Thanks for the response.
Jim: The case where A = fn(B + C) is a particularly challenging one to implement in a leak free manner, and AFAIK, it necessitates reference counting to implement. My example code is similar to this, as the assignment operator has been overloaded to accomodate type extended polymorphic variables. So the leaky line looks like A = B // C but it is effectively equivalent to CALL Assign( A, (B // C) ) where the first argument to Assign is intent(inout) and the second argument is intent(in)
- Mark as New
- Bookmark
- Subscribe
- Mute
- Subscribe to RSS Feed
- Permalink
- Report Inappropriate Content
Zaak,
You do not need reference counting on the (B//C). The compiler knows there is only one refference and that the reference lifetime expires at the end of the statement (where it can be destroyed). Note, the CALL Assign second argument could not have intent(out) or inout attribute or implicit inout as this would be in error.
Jim Dempsey

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