I’ve had a question for a long time;) Is deallocation really necessary within a program?
Without deallocation:
program test
implicit none
real, allocatable :: a(:)
allocate(a(1))
! deallocate(a)
end program
Running with Valgrind:
gfortran -g test.f90 && valgrind -s --leak-check=full --show-leak-kinds=all --track-origins=yes ./a.out
Results:
==1484510== Memcheck, a memory error detector
==1484510== Copyright (C) 2002-2024, and GNU GPL'd, by Julian Seward et al.
==1484510== Using Valgrind-3.24.0.GIT and LibVEX; rerun with -h for copyright info
==1484510== Command: ./a.out
==1484510==
==1484510==
==1484510== HEAP SUMMARY:
==1484510== in use at exit: 4 bytes in 1 blocks
==1484510== total heap usage: 18 allocs, 17 frees, 5,448 bytes allocated
==1484510==
==1484510== 4 bytes in 1 blocks are definitely lost in loss record 1 of 1
==1484510== at 0x484B77B: malloc (vg_replace_malloc.c:446)
==1484510== by 0x401210: MAIN__ (test.f90:5)
==1484510== by 0x401295: main (test.f90:7)
==1484510==
==1484510== LEAK SUMMARY:
==1484510== definitely lost: 4 bytes in 1 blocks
==1484510== indirectly lost: 0 bytes in 0 blocks
==1484510== possibly lost: 0 bytes in 0 blocks
==1484510== still reachable: 0 bytes in 0 blocks
==1484510== suppressed: 0 bytes in 0 blocks
==1484510==
==1484510== ERROR SUMMARY: 1 errors from 1 contexts (suppressed: 0 from 0)
With deallocation:
program test
implicit none
real, allocatable :: a(:)
allocate(a(1))
deallocate(a)
end program
Results:
==1500356== Memcheck, a memory error detector
==1500356== Copyright (C) 2002-2024, and GNU GPL'd, by Julian Seward et al.
==1500356== Using Valgrind-3.24.0.GIT and LibVEX; rerun with -h for copyright info
==1500356== Command: ./a.out
==1500356==
==1500356==
==1500356== HEAP SUMMARY:
==1500356== in use at exit: 0 bytes in 0 blocks
==1500356== total heap usage: 18 allocs, 18 frees, 5,448 bytes allocated
==1500356==
==1500356== All heap blocks were freed -- no leaks are possible
==1500356==
==1500356== ERROR SUMMARY: 0 errors from 0 contexts (suppressed: 0 from 0)
The same question arises when using derived types: is it really necessary to call t%deallocate()
in the following example?
module mod_test
implicit none
type type_t
real, allocatable :: a(:)
contains
procedure :: set
procedure :: deallocate
end type
contains
subroutine set(this, a)
class(type_t), intent(inout) :: this
real, intent(in) :: a(:)
this%a = a
end subroutine
subroutine deallocate(this)
class(type_t), intent(inout) :: this
if (allocated(this%a)) deallocate(this%a)
end subroutine
end module
program test
use mod_test
implicit none
type(type_t) :: t
real, allocatable :: a(:)
allocate(a(1), source=0.0)
call t%set(a)
deallocate(a)
call t%deallocate()
end program