ifort generating leaky code?

ifort generating leaky code?

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:

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

The code generated by

 
$ ifort -V
Intel(R) Fortran Intel(R) 64 Compiler XE for applications running on Intel(R) 64, Version 13.1.0.146 Build 20130121 

seems to leak at line 41 in ConcatChars (which is being called via the overloaded operator //)

The code was compiled as:

$ ifort -g -O0 -assume realloc_lhs -o memleak bug.f90
on a RHEL 5 x86_64 machine and the leak was found via
$ valgrind --leak-check ./memleak
The valgrind output is attached.

I think this might be a compiler bug.

Thanks,

AttachmentSize
Downloadtext/plain memleak.valgrind.txt19.61 KB
-Zaak
5 posts / 0 new
Last post
For more complete information about compiler optimizations, see our Optimization Notice.

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

www.quickthreadprogramming.com

I can reproduce this and have escalated it to the developers as issue DPD200244704. Thanks for reporting it.

Steve - Intel Developer Support

Quote:

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)

-Zaak

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

www.quickthreadprogramming.com

Leave a Comment

Please sign in to add a comment. Not a member? Join today