проблема с финальной процедурой (segfault с gfortran)

рассмотрите следующую небольшую программу, которая воспроизводит ошибку сегментации, которую я получаю с gfortran gcc 9.2.0 для mac 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

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


person R. Hassani    schedule 24.01.2020    source источник
comment
Поскольку последняя подпрограмма в этой программе не вызывается, первое предположение должно заключаться в том, что ваш компилятор ведет себя непослушно.   -  person francescalus    schedule 24.01.2020


Ответы (2)


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

Ибо проблема в gfortran есть.

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

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

  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

or

  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. В качестве скалярного компонента явной длины (распределяемого) приведенные выше примеры аварийно завершают работу с финализацией или без нее; поскольку финализация компонента отложенной длины контролирует сбой.

person francescalus    schedule 24.01.2020
comment
Оба примера компилируются и выполняются с помощью gfortran 10.0.0 2019122. - person evets; 24.01.2020
comment
(Я тестировал с 9.1, а не с более поздней 9 или транком). - person francescalus; 24.01.2020
comment
Спасибо, интересно (но несколько тревожно!). У меня пока нет доступа к gcc 10, надеюсь, это исправят. - person R. Hassani; 24.01.2020
comment
@francescalus, код OP не завершается. Есть несколько отчетов об ошибках gfortran, связанных с финализацией. К сожалению, gfortran недавно потерял несколько разработчиков. - person evets; 25.01.2020
comment
@evets, пример ОП и мои два, похоже, не работают с 10.0.1 20200125 в моей системе. Какие детали полезно указать? (Спасибо за обновление, но не приятно слышать о потере разработчиков.) - person francescalus; 26.01.2020

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

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

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

person HendersonSC    schedule 16.03.2020