https://gcc.gnu.org/bugzilla/show_bug.cgi?id=90069
Bug ID: 90069
Summary: Polymorphic Return Type Memory Leak Without
Intermediate Variable
Product: gcc
Version: 8.2.1
Status: UNCONFIRMED
Severity: normal
Priority: P3
Component: fortran
Assignee: unassigned at gcc dot gnu.org
Reporter: brichardson at structint dot com
Target Milestone: ---
It appears that, if a function returns a polymorphic (i.e. class(thing))
variable, if the result is not assigned to a variable, then a memory leak
occurs.
The following short program and command output demonstrates the problem.
program returned_memory_leak
implicit none
type, abstract :: base
end type base
type, extends(base) :: extended
end type extended
type :: container
class(*), allocatable :: thing
end type
call run()
contains
subroutine run()
type(container) :: a_container
a_container = theRightWay()
a_container = theWrongWay()
end subroutine
function theRightWay()
type(container) :: theRightWay
class(base), allocatable :: thing
allocate(thing, source = newAbstract())
theRightWay = newContainer(thing)
end function theRightWay
function theWrongWay()
type(container) :: theWrongWay
theWrongWay = newContainer(newAbstract())
end function theWrongWay
function newAbstract()
class(base), allocatable :: newAbstract
allocate(newAbstract, source = newExtended())
end function newAbstract
function newExtended()
type(extended) :: newExtended
end function newExtended
function newContainer(thing)
class(*), intent(in) :: thing
type(container) :: newContainer
allocate(newContainer%thing, source = thing)
end function newContainer
end program returned_memory_leak
$ gfortran -g returned_memory_leak.f90 -o returned_memory_leak
$ valgrind --leak-check=full ./returned_memory_leak
==7972== Memcheck, a memory error detector
==7972== Copyright (C) 2002-2017, and GNU GPL'd, by Julian Seward et al.
==7972== Using Valgrind-3.14.0 and LibVEX; rerun with -h for copyright info
==7972== Command: ./returned_memory_leak
==7972==
==7972==
==7972== HEAP SUMMARY:
==7972== in use at exit: 3 bytes in 3 blocks
==7972== total heap usage: 27 allocs, 24 frees, 13,526 bytes allocated
==7972==
==7972== 1 bytes in 1 blocks are definitely lost in loss record 1 of 3
==7972== at 0x483777F: malloc (vg_replace_malloc.c:299)
==7972== by 0x1093BD: newabstract.3812 (returned_memory_leak.f90:41)
==7972== by 0x109601: therightway.3816 (returned_memory_leak.f90:28)
==7972== by 0x1098BE: run.3818 (returned_memory_leak.f90:19)
==7972== by 0x1091D6: MAIN__ (returned_memory_leak.f90:14)
==7972== by 0x109AD4: main (returned_memory_leak.f90:14)
==7972==
==7972== 1 bytes in 1 blocks are definitely lost in loss record 2 of 3
==7972== at 0x483777F: malloc (vg_replace_malloc.c:299)
==7972== by 0x1093BD: newabstract.3812 (returned_memory_leak.f90:41)
==7972== by 0x10945E: thewrongway.3814 (returned_memory_leak.f90:35)
==7972== by 0x109965: run.3818 (returned_memory_leak.f90:20)
==7972== by 0x1091D6: MAIN__ (returned_memory_leak.f90:14)
==7972== by 0x109AD4: main (returned_memory_leak.f90:14)
==7972==
==7972== 1 bytes in 1 blocks are definitely lost in loss record 3 of 3
==7972== at 0x483777F: malloc (vg_replace_malloc.c:299)
==7972== by 0x1093BD: newabstract.3812 (returned_memory_leak.f90:41)
==7972== by 0x10946D: thewrongway.3814 (returned_memory_leak.f90:35)
==7972== by 0x109965: run.3818 (returned_memory_leak.f90:20)
==7972== by 0x1091D6: MAIN__ (returned_memory_leak.f90:14)
==7972== by 0x109AD4: main (returned_memory_leak.f90:14)
==7972==
==7972== LEAK SUMMARY:
==7972== definitely lost: 3 bytes in 3 blocks
==7972== indirectly lost: 0 bytes in 0 blocks
==7972== possibly lost: 0 bytes in 0 blocks
==7972== still reachable: 0 bytes in 0 blocks
==7972== suppressed: 0 bytes in 0 blocks
==7972==
==7972== For counts of detected and suppressed errors, rerun with: -v
==7972== ERROR SUMMARY: 3 errors from 3 contexts (suppressed: 0 from 0)
Note, whatever leak is happening in theRightWay function appears to have been
fixed in the version of 9.0 from September that we are using at work, so don't
worry about that one for this bug report.
I'm using the official version on Arch Linux in the above.