https://gcc.gnu.org/bugzilla/show_bug.cgi?id=90076

            Bug ID: 90076
           Summary: Polymorphic Allocate on Assignment Memory Leak
           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: ---

Allocate on assignment for polymorphic scalars causes a memory leak. The
following program and execution demonstrates the problem.

program assignment_memory_leak
    implicit none

    type, abstract :: base
    end type base

    type, extends(base) :: extended
    end type extended

    call run()
contains
    subroutine run()
        class(base), allocatable :: var

        allocate(var, source = newVar())
        var = newVar() ! This is a memory leak
    end subroutine run

    function newVar()
        class(base), allocatable :: newVar

        allocate(newVar, source = extended())
    end function newVar
end program assignment_memory_leak

$ gfortran -g assignment_memory_leak.f90 -o assignment_memory_leak
$ valgrind --leak-check=full ./assignment_memory_leak             
==10130== Memcheck, a memory error detector
==10130== Copyright (C) 2002-2017, and GNU GPL'd, by Julian Seward et al.
==10130== Using Valgrind-3.14.0 and LibVEX; rerun with -h for copyright info
==10130== Command: ./assignment_memory_leak
==10130== 
==10130== 
==10130== HEAP SUMMARY:
==10130==     in use at exit: 2 bytes in 2 blocks
==10130==   total heap usage: 24 allocs, 22 frees, 13,523 bytes allocated
==10130== 
==10130== 1 bytes in 1 blocks are definitely lost in loss record 1 of 2
==10130==    at 0x483777F: malloc (vg_replace_malloc.c:299)
==10130==    by 0x109241: newvar.3789 (assignment_memory_leak.f90:22)
==10130==    by 0x1092D9: run.3791 (assignment_memory_leak.f90:15)
==10130==    by 0x1091D6: MAIN__ (assignment_memory_leak.f90:10)
==10130==    by 0x10947F: main (assignment_memory_leak.f90:10)
==10130== 
==10130== 1 bytes in 1 blocks are definitely lost in loss record 2 of 2
==10130==    at 0x483777F: malloc (vg_replace_malloc.c:299)
==10130==    by 0x109241: newvar.3789 (assignment_memory_leak.f90:22)
==10130==    by 0x10936B: run.3791 (assignment_memory_leak.f90:16)
==10130==    by 0x1091D6: MAIN__ (assignment_memory_leak.f90:10)
==10130==    by 0x10947F: main (assignment_memory_leak.f90:10)
==10130== 
==10130== LEAK SUMMARY:
==10130==    definitely lost: 2 bytes in 2 blocks
==10130==    indirectly lost: 0 bytes in 0 blocks
==10130==      possibly lost: 0 bytes in 0 blocks
==10130==    still reachable: 0 bytes in 0 blocks
==10130==         suppressed: 0 bytes in 0 blocks
==10130== 
==10130== For counts of detected and suppressed errors, rerun with: -v
==10130== ERROR SUMMARY: 2 errors from 2 contexts (suppressed: 0 from 0)

Note that using a version of 9.0 from September that we use at work, the
explicit allocate doesn't generate a memory leak, so I'm not worried about that
for this bug report.

Additionally, If I make the newVar function return the concrete type, I don't
get any memory leaks.

program assignment_memory_leak
    implicit none

    type, abstract :: base
    end type base

    type, extends(base) :: extended
    end type extended

    call run()
contains
    subroutine run()
        class(base), allocatable :: var

        allocate(var, source = newVar())
        var = newVar() ! This is fine now
    end subroutine run

    function newVar()
        type(extended) :: newVar
    end function newVar
end program assignment_memory_leak

$ gfortran -g assignment_memory_leak.f90 -o assignment_memory_leak
$ valgrind --leak-check=full ./assignment_memory_leak             
==10176== Memcheck, a memory error detector
==10176== Copyright (C) 2002-2017, and GNU GPL'd, by Julian Seward et al.
==10176== Using Valgrind-3.14.0 and LibVEX; rerun with -h for copyright info
==10176== Command: ./assignment_memory_leak
==10176== 
==10176== 
==10176== HEAP SUMMARY:
==10176==     in use at exit: 0 bytes in 0 blocks
==10176==   total heap usage: 22 allocs, 22 frees, 13,521 bytes allocated
==10176== 
==10176== All heap blocks were freed -- no leaks are possible
==10176== 
==10176== For counts of detected and suppressed errors, rerun with: -v
==10176== ERROR SUMMARY: 0 errors from 0 contexts (suppressed: 0 from 0)

But if I remove the allocate statement, the compiler segfaults.

program assignment_memory_leak
    implicit none

    type, abstract :: base
    end type base

    type, extends(base) :: extended
    end type extended

    call run()
contains
    subroutine run()
        class(base), allocatable :: var

        var = newVar() ! This segfaults the compiler
    end subroutine run

    function newVar()
        type(extended) :: newVar
    end function newVar
end program assignment_memory_leak

$ gfortran -g assignment_memory_leak.f90 -o assignment_memory_leak
assignment_memory_leak.f90:15:0:

         var = newVar() ! This segfaults the compiler

internal compiler error: in build_function_decl, at fortran/trans-decl.c:2238
Please submit a full bug report,
with preprocessed source if appropriate.
See <https://bugs.archlinux.org/> for instructions.

Those behaviors are the same for the version of 9.0 I use at work.

I used the official version for Arch Linux to generate all of the above.

Reply via email to