Должна ли процедура завершения быть элементарной, чтобы ее можно было вызывать для элементов выделяемого массива, выходящего за пределы области видимости?

Если у меня есть выделяемый массив финализируемого производного типа, будет ли финализатор вызываться для каждого отдельного элемента, когда массив выходит за пределы области видимости?

Вот небольшой пример кода, который иллюстрирует вопрос:

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

Обратите внимание, что эта программа пропускает массив dontLeakMe, выделенный в New() методе LeakyType. Сначала это было немного удивительно для меня, но потом я обнаружил, что проблему можно решить, объявив финализатор elemental. И gfortran, и ifort ведут себя одинаково, поэтому я предполагаю, что это поведение соответствует стандарту Fortran 2003.

Кто-нибудь может это подтвердить? Честно говоря, мне трудно понять, что стандарт говорит по этому поводу.

Прямо сейчас я также не вижу особого смысла в том, чтобы не объявлять все мои финализаторы элементарными. Есть ли здесь какое-нибудь приложение, которое я не замечаю?


person Robert Rüger    schedule 07.04.2017    source источник
comment
Вы видели этот вопрос?   -  person francescalus    schedule 07.04.2017
comment
Нет, я этого не видел. Таким образом, в основном нужно предоставить отдельные финализаторы для массивов всех разных рангов, и объявление скалярного элемента финализатора - всего лишь удобный способ сделать это? Я все еще не понимаю, для чего это нужно, но ладно. Большое спасибо за ваш комментарий! :)   -  person Robert Rüger    schedule 07.04.2017
comment
Я могу представить, что массив производного типа может быть таким, что элементарная доработка может быть сложной задачей. Но я не могу сразу привести пример.   -  person francescalus    schedule 07.04.2017


Ответы (1)


Правила определения того, вызывается ли последняя процедура и какая последняя процедура вызывается, такие же, как и для разрешения общих процедур с точки зрения требований сопоставления рангов.

Заметим, что вопрос помечен как Fortran 2003 ...

Элементарные процедуры в Fortran 2003 и ранее должны быть PURE. Если вашему финализатору нужно сделать что-то несовместимое с чистым атрибутом (что достаточно часто), то финализатор не может быть элементарным, и вам нужно написать варианты, зависящие от ранга.

Fortran 2008 представляет концепцию IMPURE ELEMENTAL, которая очень удобна для написания финализаторов.

person IanH    schedule 13.04.2017