最终程序的问题(gfortran 的段错误)

R. *_*ani 5 fortran finalizer gfortran

考虑下面的小程序,它重现了我在 mac os 上使用 gfortran gcc 9.2.0 时遇到的分段错误):

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
Run Code Online (Sandbox Code Playgroud)

仅当释放具有 str_t 类型的显式数组成员的 static_t 类型的数组时,才会发生段错误。奇怪的是,它似乎与 str_t DT 的最终方法有关(当我删除此过程时,问题就消失了),但我没有看到原因。

fra*_*lus 3

这看起来确实像最终子例程的问题,毕竟删除最终子例程可以消除分段错误。然而,这是 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
Run Code Online (Sandbox Code Playgroud)

或者

  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
Run Code Online (Sandbox Code Playgroud)

两者都没有看到最终确定,但在运行时都出现了(对我来说)分段错误。

如果您想查看问题的程序与此答案之间的联系:关键是组件的延迟长度性质。s作为显式长度(可分配)标量组件,上面的示例在有或没有最终确定的情况下都会崩溃;作为延迟长度组件完成控制崩溃。