The short answer is IT DEPENDS. (Initially, I wrote YES, but I’ve changed opinion meanwhile.)
A previous discussion can be found here: Automatic finalization of derived types. To summarize that discussion, variables in the main program scope have the implicit save
attribute, and the standard states that such variables are not finalized as a result of an end [program]
statement.
If you want automatic deallocation to take place, you can wrap the contents of the main program in a subroutine or a block construct:
! DEALLOCATION VIA BLOCK
program test
implicit none
block
use mod_test
type(type_t) :: t
real, allocatable :: a(:)
allocate(a(1), source=0.0)
call t%set(a)
end block
end program
! DEALLOCATION VIA SUBROUTINE
program test
implicit none
call run
contains
subroutine run()
use mod_test
type(type_t) :: t
real, allocatable :: a(:)
allocate(a(1), source=0.0)
call t%set(a)
end subroutine
end program
Whether this is really necessary or not seems to be a matter of taste. At least for memory, on systems providing virtual memory, after termination the operating system will reclaim the memory belonging to the process anyways.
But if your derived type handles some other type of “resource”, for example related to IPC such as a pipe, socket, etc., then closing it correctly so that the other communicating process can respond correctly, would be the right thing to do.