Does the finalization routine need to be elemental

2020-02-14 08:25发布

问题:

If I have an allocatable array of a finalizable derived type, will the finalizer be called on every individual element when the array goes out of scope?

Here is a small code example that illustrates the question:

module LeakyTypeModule

   implicit none
   private

   type, public :: LeakyType
      real, pointer :: dontLeakMe(:) => null()
   contains
      procedure :: New
      final     :: Finalizer
   end type

contains

   subroutine New(self, n)
      class(LeakyType), intent(out) :: self
      integer         , intent(in)  :: n
      allocate(self%dontLeakMe(n))
      self%dontLeakMe = 42.0
   end subroutine

   subroutine Finalizer(self)
      type(LeakyType), intent(inout) :: self
      if (associated(self%dontLeakMe)) deallocate(self%dontLeakMe)
   end subroutine

end module


program leak

   use LeakyTypeModule
   implicit none

   type(LeakyType), allocatable :: arr(:)

   allocate(arr(1))
   call arr(1)%New(1000)
   deallocate(arr)

end program

Note that this program leaks the dontLeakMe array allocated in the New() method of LeakyType. At first this was a bit surprising for me but, then I discovered that the problem can be fixed by declaring the finalizer elemental. Both gfortran and ifort behave in the same way, so I assume this behaviour is following the Fortran 2003 standard.

Can anyone confirm this? To be honest I have a hard time time understanding what the standard says on this particular point.

Right now I also can't see much use in not declaring all my finalizers elemental. Does this have any application I'm overlooking?

回答1:

The rules for determining whether a final procedure is invoked, and which final procedure is invoked, are the same as for resolution of generic procedures in terms of rank matching requirements.

Noting that the question is tagged Fortran 2003...

Elemental procedures in Fortran 2003 and prior have to be PURE. If your finalizer needs to do something that is incompatible with the pure attribute (which is reasonably common) then the finalizer cannot be elemental, and you need to write the rank specific variants.

Fortran 2008 introduces the concept of IMPURE ELEMENTAL, which is quite handy for writing finalizers.