проблема с финальной процедурой (сегфо с гфортраном) - PullRequest
4 голосов
/ 24 января 2020

рассмотрим следующую небольшую программу, которая воспроизводит ошибку сегментации, которую я получаю с помощью gfortran g cc 9.2.0 для ma c os):

module stringmod

   type :: str_t
      character(len=:), allocatable :: s
   contains
      final :: finalize
   end type str_t   

   type :: static_t  
      type(str_t) :: expr(3)
   end type static_t

   type :: dynamic_t  
      type(str_t), allocatable :: expr(:)
   end type dynamic_t

contains

   subroutine finalize ( x )
      type(str_t), intent(in out) :: x

      if (allocated(x%s)) deallocate(x%s)    

   end subroutine finalize

end module stringmod

use stringmod

implicit none

type(static_t ), allocatable :: stat(:)
type(dynamic_t), allocatable :: dyna(:)
integer                      :: i, j, n = 10

allocate(stat(n),dyna(n))

do i = 1, n
   allocate(dyna(i)%expr(3))
end do

! No problem when deallocating "dyna":
deallocate(dyna)

! while deallocating "stat"causes a segfault with gfortran (gcc 9.2.0 for mac os)
! (unless the final method is removed from the DT):

deallocate(stat) 

end

Сегфоут происходит только при освобождении массива Тип static_t, который имеет явный член массива типа str_t. Как ни странно, это похоже на последний метод str_t DT (когда я удаляю эту процедуру, проблема исчезает), но я не вижу причины.

Ответы [ 2 ]

2 голосов
/ 24 января 2020

Это похоже на проблему с последними подпрограммами, ведь удаление последней подпрограммы устраняет ошибку сегментации. Тем не менее, это один из примеров более широкого класса проблем в gfortran.

Для проблемы в gfortran это так.

В вашем случае у вас есть доступное решение: удалите последнюю подпрограмму, которая на самом деле не вызывается в любой момент. В более общих случаях это может быть не вариант. В любом случае нужно сообщить об этой ошибке сопровождающим G CC (особенно, если вы можете протестировать более поздние версии компилятора).

Почему я говорю об этой части более широкой проблемы? Давайте посмотрим на упрощение вашего кода:

  type :: str_t
     character, allocatable :: s
  end type str_t

  type :: dynamic_t  
     type(str_t), allocatable :: expr
  end type dynamic_t

  type(dynamic_t), allocatable :: dyna

  allocate(dyna)
  allocate(dyna%expr)

end

или

  implicit none

  type :: str_t
     character, allocatable :: s
  end type str_t

  type :: static_t  
     type(str_t) :: expr
  end type static_t

  type(static_t), allocatable :: stat
  allocate(stat)

end

Ни один из них не имеет финализации, но оба присутствуют (для меня) при сегментировании при запуске.

Если вы хотите увидеть связь между программой вопроса и этим ответом: это отложенная длина характер компонента s, который является ключевым. В качестве скалярного компонента явной длины (выделяемого) приведенные выше примеры cra sh с завершением или без него; в качестве компонента отложенной длины финализация контролирует cra sh.

0 голосов
/ 16 марта 2020

Сначала я бы прокомментировал, но я не обычный пользователь, поэтому моего представителя там нет. У меня поразительно похожая проблема, и я ценю готовый пример, который, кажется, работает с g cc 5.4, учитывающим это предостережение:

  • флаги по умолчанию, -O1, -O2 - все сбой
  • -Og и -O3 работают как положено

Очевидно, что это не то, что вы хотите написать код, но хотели передать мой опыт, и если вы отправили отчет об ошибке, это может быть полезной информацией для них. Я получаю такое же поведение на своем ноутбуке Ubuntu с g cc 9.2.1.

...