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.