Fortran массив производных типов и утечек памяти несмотря на завершение

Я определил производный тип и столкнулся с некоторыми проблемами с освобождением памяти, хотя я написал окончательную процедуру. Код выглядит следующим образом

module ModuleCoordinate
  implicit none

  type :: TCoordinate
    real(8),dimension(:),pointer :: Coordinate => NULL()
    contains
      procedure :: TCoordinateAssignment
      generic,public :: Assignment(=) => TCoordinateAssignment
      final :: TCoordinateDel
  end type TCoordinate

  interface TCoordinate
    module procedure :: TCoordinateInit
  end interface TCoordinate

  contains
    subroutine TCoordinateDel(self)
      type(TCoordinate),intent(inout) :: self
      if(associated(self%Coordinate))deallocate(self%Coordinate)
    end subroutine TCoordinateDel

    subroutine TCoordinateAssignment(O1,O2)
      class(TCoordinate),intent(out) :: O1
      type(TCoordinate),intent(in) :: O2
      if(associated(O2%Coordinate))allocate(O1%Coordinate,source=O2%Coordinate)
    end subroutine TCoordinateAssignment

    type(TCoordinate) function TCoordinateInit(IVal1,IVal2) result(self)
      real(8),intent(in) :: IVal1,IVal2
      allocate(self%Coordinate(2))
      self%Coordinate=(/IVal1,IVal2/)
    end function TCoordinateInit
end module ModuleCoordinate

Тестовый код выглядит следующим образом

program test
  implicit none
  integer(4),parameter :: NLoop=40000
  integer(4) :: i
  do i=1,NLoop
    call TestMemory1()
    call TestMemory2()
  end do
  pause
end program test

subroutine TestMemory1()
  use ModuleCoordinate
  implicit none
  integer(4),parameter :: DN=10
  integer(4) :: i
  type(TCoordinate),dimension(DN) :: a
  do i=1,DN
    a(i)=TCoordinate(1.0_8,1.0_8)
  end do
end subroutine TestMemory1

subroutine TestMemory2()
  use ModuleCoordinate
  implicit none
  type(TCoordinate) :: b1,b2,b3,b4,b5,b6,b7,b8,b9,b10
  b1=TCoordinate(1.0_8,1.0_8)
  b2=TCoordinate(1.0_8,1.0_8)
  b3=TCoordinate(1.0_8,1.0_8)
  b4=TCoordinate(1.0_8,1.0_8)
  b5=TCoordinate(1.0_8,1.0_8)
  b6=TCoordinate(1.0_8,1.0_8)
  b7=TCoordinate(1.0_8,1.0_8)
  b8=TCoordinate(1.0_8,1.0_8)
  b9=TCoordinate(1.0_8,1.0_8)
  b10=TCoordinate(1.0_8,1.0_8)
end subroutine TestMemory2

Оказывается, подпрограмма TestMemory2 пока нормально TestMemory1 это не так, что означает, что при объявлении массива этого производного типа последняя процедура не работает и происходит утечка памяти.

Однако, если я удалю => NULL() справа от Coordinate в определении этого производного типа обе подпрограммы, кажется, работают хорошо.

Что имеет значение, когда указатель Coordinate освобождается? Компилятором является ifort_2013_sp1.3.174, если это имеет значение.

1 ответ

В описании процесса завершения мы видим (Fortran 2008, 4.5.6.2)

Если динамический тип сущности имеет заключительную подпрограмму, фиктивный аргумент которой имеет те же параметры типа вида и ранга, что и завершаемая сущность, он вызывается с сущностью в качестве фактического аргумента. В противном случае, если есть элементарная конечная подпрограмма, фиктивный аргумент которой имеет те же параметры типа вида, что и завершаемая сущность, она вызывается с сущностью в качестве фактического аргумента. В противном случае подпрограмма не вызывается в этой точке.

Существует заключительная подпрограмма для производного типа, предоставленная только для скалярных (ранг-0) объектов. Чтобы получить финализацию для вашей сущности ранга 1, самый простой способ (кажется, в данном случае) - сделать подпрограмму элементарной.

Я немного не хочу упоминать =>NULL() аспект, поскольку у меня нет текущих средств проверки того, что я собираюсь написать, но я буду размышлять.

Без =>NULL() инициализация по умолчанию компонент указателя имеет неопределенный статус ассоциации. Это означает, что когда вы делаете

    b1=TCoordinate(1.0_8,1.0_8)

происходят интересные вещи.

В рамках задания b1 завершается при входе в TCoordinateAssignment, Финализация включает в себя вызов associated с указателем, который имеет неопределенный статус ассоциации. Это недопустимо (в результате чего может возникнуть любой результат).

Другие вопросы по тегам