考虑下面的小程序,该程序再现了我用gfortran gcc 9.2.0 for 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
仅当取消分配具有str_t类型的显式数组成员的static_t类型的数组时,才会发生段错误。奇怪的是,它似乎与str_t DT的最终方法有关(当我删除此过程时,问题就消失了),但我看不出原因。
对于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
或
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
的deferred length性质。作为显式长度(可分配)标量组件,以上示例在有或没有完成的情况下都崩溃了;因为延迟长度的组件完成控制了崩溃。
gcc-9.2
似乎还有其他问题在这种情况下
program optional_test
integer :: x, y, z
x = 1
y = 2
call add(x, y, z)
contains
subroutine add(x, y, z, debug)
integer, intent(in) :: x, y
integer, intent(out) :: z
logical, intent(in), optional :: debug
if(present(debug) .and. debug) then
print *, 'debug mode'
end if
z = x + y
end subroutine add
end program optional_test
在执行期间抛出了SIGSEGV
。gcc-8.3
正常工作。