Dear all,
I faced with a possible serious bug: polymorphic functions (necessary
to define polymorphic operators in OOP programs) generate memory leaks
making OOP program not feasible.
I opened a bug report (80477) here
https://gcc.gnu.org/bugzilla/show_bug.cgi?id=80477
I report the details also below.
My best regards.
Issue summary
In the attached example "polymorphic_operators_memory_leaks.f90" I
show the possible bug in less than 100 lines. Essentially, the derived
type "a_type_t" defines the operators "=" and "+" in a polymorphic way
(in order to allow "a_type_t" to be extended while all other "agents"
using "a_type_t" do not need to be changed, OOP). The assignment
operator does not create memory leaks because it is subroutine that
does not allocate temporary. On the contrary, the operator "+" is a
function that allocates a temporary: this temporary generates the
memory leaks because it is not correctly destroyed after its usage.
I checked the above conclusion with "valgrind" and it confirms that
the "+" operator (function) generates the leaks. Note that the same
code compiled and run with Intel Fortran (17.0.2) does not generates
memory leaks and it works as expected. Moreover, is the "+"
operator/function is modified disallowing polymorphic (namely changing
"class(a_type_t), allocatable :: res" with "type(a_type_t) :: res" the
leaks disappear, thus I could conclude that the leaks are generated
only for polymorphic function results.
A word of advice: the test is designed to point out the memory leaks
occurrences, running it your RAM will be quickly consumed! Please, be
rapid to quickly kill it before your OS start swapping on HD. To test
it with valgrind I added a little "ui": it can be executed without
arguments, thus its loop will be very long (and your RAM totally
consumed) or you can pass one integer argument and the loop will do
the iterations you provided, e.g. "a.out 1" will execute 1 iteration
loop. This is written into the code comments.
Please, consider that if this is really a bug, all serious OOP
programs are indeed impossible to be done.
Thank you very much for your help.
Stefano Zaghi Ph.D. Aerospace Engineer
Research Scientist, Dept. of Computational Hydrodynamics at CNR-INSEAN
p: +39 0650299260 | m: +39 3497730036 | e: [email protected]
Member of Fortran-FOSS-Programmers
Codes Showcase
OFF Open source Finite volumes Fluid dynamics code
Lib_VTK_IO Fortran library to write and read data conforming the VTK standard
FLAP Fortran command Line Arguments Parser for poor men
BeFoR64 Base64 encoding/decoding library for FoRtran poor men
FiNeR Fortran INI ParseR and generator for FoRtran poor men
IR_Precision Fortran (standard 2003) module to develop portable codes
FoBis.py Fortran Building System for poor men
PreForM.py Preprocessor for Fortran poor men
MaTiSSe.py Markdown To Impressive Scientific Slides
module a_type_m
implicit none
integer, parameter :: LENGTH = 100
type :: a_type_t
real :: x(LENGTH)
contains
! operators
generic :: assignment(=) => assign_a_type
generic :: operator(+) => add_a_type
procedure, pass(lhs) :: assign_a_type
procedure, pass(lhs) :: add_a_type
endtype a_type_t
contains
subroutine assign_a_type(lhs, rhs)
! Operator `=`.
class(a_type_t), intent(inout) :: lhs
class(a_type_t), intent(in) :: rhs
lhs%x = rhs%x
endsubroutine assign_a_type
function add_a_type(lhs, rhs) result( res )
! Operator `+`.
class(a_type_t), intent(in) :: lhs
class(a_type_t), intent(in) :: rhs
class(a_type_t), allocatable :: res
allocate (a_type_t :: res)
res%x = lhs%x + rhs%x
endfunction add_a_type
endmodule a_type_m
program polymorphic_operators_memory_leaks
! pass one argument to limit the loop iterations, e.g.:
! a.out 4 # the loop will be limited to 4 iterations
! useful for testing with valgrind;
! a.out # the loop will run for LENGHT**3 iterations
use a_type_m
implicit none
character(99) :: switch
type(a_type_t) :: a
type(a_type_t) :: b
integer :: N
integer :: i
a%x = [(i, i=1, LENGTH)]
b = a
i = command_argument_count()
if (i == 1) then
call get_command_argument(1,switch)
read(switch, *) N
else
N = LENGTH**3
endif
do i=1, N
b = a + b ! here the `+` operator generates memory leaks
if (mod(i,10**5) == 0) print*, i
enddo
endprogram polymorphic_operators_memory_leaks