在 Fortran 中正确执行 Final 例程
Correct execution of Final routine in Fortran
我有以下 Fortran 代码
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
而在我的主程序中打印时它看起来已被释放,因为它给我一个分段错误
取消分配指针会导致与同一目标关联的任何其他指针的指针关联状态变为未定义 (F2018 9.7.3.3p2)。这种情况发生在 DESTROY_OCTREE
过程中的 node
和 this%root
- 两个指针都引用同一个对象(通过指针赋值 node => this% root
,对象通过 node
指针 - 这使得 this%root
具有未定义的关联状态。
ASSOCIATED 内部函数的参数不能是具有未定义关联状态的指针 (F2018 16.9.16p3)。代码不符合规范,任何事情都可能发生 - "anything" 相当合理地包含了您看到的结果。
当您通过 node
指针解除分配对象时,没有简单的方法让处理器也可以可靠地更新 this%root
指针的状态 - 它最终指向一些不不再存在。
在显示的源代码片段中还有其他可疑结构,包括在同一指针对象上的 DEALLOCATE 语句之后使用多余的 NULLIFY(成功的解除分配取消关联(使指针无效)),当 DEALLOCATE 可能是适当的(如果没有完整的代码很难说),以及使用结构构造函数作为指针目标。
我有以下 Fortran 代码
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
而在我的主程序中打印时它看起来已被释放,因为它给我一个分段错误
取消分配指针会导致与同一目标关联的任何其他指针的指针关联状态变为未定义 (F2018 9.7.3.3p2)。这种情况发生在 DESTROY_OCTREE
过程中的 node
和 this%root
- 两个指针都引用同一个对象(通过指针赋值 node => this% root
,对象通过 node
指针 - 这使得 this%root
具有未定义的关联状态。
ASSOCIATED 内部函数的参数不能是具有未定义关联状态的指针 (F2018 16.9.16p3)。代码不符合规范,任何事情都可能发生 - "anything" 相当合理地包含了您看到的结果。
当您通过 node
指针解除分配对象时,没有简单的方法让处理器也可以可靠地更新 this%root
指针的状态 - 它最终指向一些不不再存在。
在显示的源代码片段中还有其他可疑结构,包括在同一指针对象上的 DEALLOCATE 语句之后使用多余的 NULLIFY(成功的解除分配取消关联(使指针无效)),当 DEALLOCATE 可能是适当的(如果没有完整的代码很难说),以及使用结构构造函数作为指针目标。