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.

Reply via email to