Правильное выполнение Финальной рутины в Фортране - PullRequest
0 голосов
/ 28 декабря 2018

У меня следующий код на Фортране

  type t_octree
     integer                        :: max_num_point
     class(t_octree_node), pointer  :: root => null()
     contains
     final                         :: DESTROY_OCTREE
  end type t_octree

  type t_octree_node
     real                          :: box(2,3)
     integer                       :: depth
     type(t_octree_node), pointer  :: parent      => null()
     type(t_octree_node), pointer  :: children(:) => null()
     class(t_octree_leaf), pointer :: leaf        => null()
  contains
     final                         :: CLEAN_NODE
  end type t_octree_node
  type, extends(t_octree_node) :: t_octree_leaf
     integer, allocatable          :: id(:)
     integer                       :: num_point
  contains
     final                          :: DESTROY_LEAF
  end type

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

В моих `заключительных процедурах у меня есть

  subroutine DESTROY_OCTREE( this )

  implicit none

  type(t_octree)               :: this
  type(t_octree_node), pointer :: node => null()
  integer                      :: i


  node => this% root
  if( associated(node% leaf) )deallocate( node% leaf )

  if(.not. associated(node% children) )RETURN
  deallocate(  node )
  node => this% root
  i = 0
  nullify(node)
  print*, associated(this% root) ! this is true!! 
  print*, associated(this% root% children) ! this is true!! 



  end subroutine DESTROY_OCTREE

  recursive subroutine CLEAN_NODE ( this )

  implicit none

  type(t_octree_node)           :: this
  type(t_octree_node), pointer  :: node => null(), next => null()
  integer                       :: i

  if( associated(this% leaf) )then
     deallocate( this% leaf )
     nullify( this% leaf )
  endif
  if(.not. associated(this% children) )RETURN
  do i = 1, 8
     node => this% children(i)
     deallocate( node )
     nullify(node)
    ! debug
    ! print*, i, "rec"
  enddo
   nullify(this% children)
   nullify(this% parent)

  end subroutine CLEAN_NODE

  subroutine DESTROY_LEAF ( leaf )

  implicit none

  type(t_octree_leaf)        :: leaf

  deallocate( leaf% id )

  end subroutine DESTROY_LEAF

В моей основной программе я выполняю следующие действия:

  program TEST_OCTREE
  use MD_OCTREE

  implicit none

  type(t_octree), pointer               :: octree

  octree      => t_octree( max_num_point,  box )
  (...) ! all processing to build the data structure

Теперь я освобождаюсь просто

  deallocate( octree )  
  print*, associated(octree% root) ! this give a segmentation fault

Вопрос Может кто-нибудь объяснить, почему кажется, что мои print*, associated(this% root) команды по-прежнему показывают TRUE, а при печати в моей основной программе это выглядит так, как будто оно было освобождено, поскольку вызывает ошибку сегментации

1 Ответ

0 голосов
/ 28 декабря 2018

Отмена выделения указателя приводит к тому, что статус ассоциации указателя любого другого указателя, который был связан с той же целью, становится неопределенным (F2018 9.7.3.3p2).Эта ситуация происходит с node и this%root в процедуре DESTROY_OCTREE - оба указателя ссылаются на один и тот же объект (через присваивание указателя node => this% root объект освобождается через указатель node - что делает this%root иметьнеопределенный статус ассоциации.

Аргумент к свойству ASSOCIATED не должен быть указателем с неопределенным статусом ассоциации (F2018 16.9.16p3). Код не соответствует, может произойти что угодно - где «все» вполне обоснованно включаетрезультаты, которые вы видите.

Когда вы освобождаете объект через указатель node, нет простого способа, которым процессор может также надежно обновить состояние указателя this%root - он в конечном итоге указывает на что-токоторого больше не существует.

В показанных фрагментах исходного кода имеются другие подозрительные конструкции, в том числе использование лишнего NULLIFY после оператора DEALLOCATE для того же объекта указателя (успешное освобождение разъединяет (обнуляет) указатель), используйтеобнулить когда возможноDEALLOCATE подходит (трудно сказать без полного кода) и использует то, что выглядит как конструктор структуры, в качестве цели указателя.

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...