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.