3

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?

Robert Rüger
  • 851
  • 9
  • 21
  • 1
    Have you seen [this question](https://stackoverflow.com/q/28548581)? – francescalus Apr 07 '17 at 15:59
  • No, I have not seen this. So basically one has to provide separate finalizers for arrays of all different ranks and declaring the scalar finalizer elemental is just a convenient way to do just that? I still don't see what this is good for, but ok. Thank you very much for your comment! :) – Robert Rüger Apr 07 '17 at 16:09
  • 1
    I can imagine that an array of a derived type could be such that finalizing elementally could be tricky. But I can't immediately give an example. – francescalus Apr 07 '17 at 16:24

1 Answers1

3

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.

IanH
  • 21,026
  • 2
  • 37
  • 59