尽管完成了派生类型的 Fortran 数组和内存泄漏 [英] Fortran array of derived types and memory leaks despite finalization
问题描述
虽然我已经编写了最终过程,但我定义了一个派生类型并遇到了一些内存释放问题.代码如下
I defined a derived type and encountered some problems with memory deallocation although I had written the final procedure. The code is as follows
module ModuleCoordinate
implicit none
type :: TCoordinate
real(8),dimension(:),pointer :: Coordinate => NULL()
contains
procedure :: TCoordinateAssignment
generic,public :: Assignment(=) => TCoordinateAssignment
final :: TCoordinateDel
end type TCoordinate
interface TCoordinate
module procedure :: TCoordinateInit
end interface TCoordinate
contains
subroutine TCoordinateDel(self)
type(TCoordinate),intent(inout) :: self
if(associated(self%Coordinate))deallocate(self%Coordinate)
end subroutine TCoordinateDel
subroutine TCoordinateAssignment(O1,O2)
class(TCoordinate),intent(out) :: O1
type(TCoordinate),intent(in) :: O2
if(associated(O2%Coordinate))allocate(O1%Coordinate,source=O2%Coordinate)
end subroutine TCoordinateAssignment
type(TCoordinate) function TCoordinateInit(IVal1,IVal2) result(self)
real(8),intent(in) :: IVal1,IVal2
allocate(self%Coordinate(2))
self%Coordinate=(/IVal1,IVal2/)
end function TCoordinateInit
end module ModuleCoordinate
测试代码如下
program test
implicit none
integer(4),parameter :: NLoop=40000
integer(4) :: i
do i=1,NLoop
call TestMemory1()
call TestMemory2()
end do
pause
end program test
subroutine TestMemory1()
use ModuleCoordinate
implicit none
integer(4),parameter :: DN=10
integer(4) :: i
type(TCoordinate),dimension(DN) :: a
do i=1,DN
a(i)=TCoordinate(1.0_8,1.0_8)
end do
end subroutine TestMemory1
subroutine TestMemory2()
use ModuleCoordinate
implicit none
type(TCoordinate) :: b1,b2,b3,b4,b5,b6,b7,b8,b9,b10
b1=TCoordinate(1.0_8,1.0_8)
b2=TCoordinate(1.0_8,1.0_8)
b3=TCoordinate(1.0_8,1.0_8)
b4=TCoordinate(1.0_8,1.0_8)
b5=TCoordinate(1.0_8,1.0_8)
b6=TCoordinate(1.0_8,1.0_8)
b7=TCoordinate(1.0_8,1.0_8)
b8=TCoordinate(1.0_8,1.0_8)
b9=TCoordinate(1.0_8,1.0_8)
b10=TCoordinate(1.0_8,1.0_8)
end subroutine TestMemory2
事实证明,子例程 TestMemory2
正常,而 TestMemory1
不正常,这意味着当声明此派生类型的数组时,最终过程不起作用和内存泄漏.
It turns out that the subroutine TestMemory2
is OK while TestMemory1
is not, which means that when an array of this derived type is declared the final procedure doesn't work and the memory leaks.
但是,如果我删除 =>在这个派生类型的定义中
,两个子例程似乎都运行良好.Coordinate
右边的NULL()
However, if I delete the => NULL()
on the right of the Coordinate
in the definition of this derived type, both subroutines seem to work well.
当指针Coordinate
被释放时有什么不同?如果重要的话,编译器是 ifort_2013_sp1.3.174.
What makes the difference when the pointer Coordinate
is being deallocated?
The complier is ifort_2013_sp1.3.174 if it matters.
推荐答案
在对finalization过程的描述中我们看到(Fortran 2008, 4.5.6.2)
In the description of the finalization process we see (Fortran 2008, 4.5.6.2)
如果实体的动态类型有一个 final 子例程,其虚拟参数具有与正在终结的实体相同的类型参数和等级,则以实体作为实际参数调用它.否则,如果有一个基本的最终子程序,其虚拟参数具有相同的kind 类型参数作为被最终确定的实体,它以实体作为实际参数调用.否则,此时不会调用任何子程序.
If the dynamic type of the entity has a final subroutine whose dummy argument has the same kind type parameters and rank as the entity being finalized, it is called with the entity as an actual argument. Otherwise, if there is an elemental final subroutine whose dummy argument has the same kind type parameters as the entity being finalized, it is called with the entity as an actual argument. Otherwise, no subroutine is called at this point.
派生类型有一个最终子例程,仅为标量(rank-0)实体提供.为您的 1 级实体最终确定最简单的方法(在这种情况下似乎)是使您拥有的子例程成为元素.
There is a final subroutine for the derived type provided only for scalar (rank-0) entities. To have finalization for your rank-1 entity the simplest way (it seems, in this case) is to make the subroutine you have elemental.
我不太愿意提及 =>NULL()
方面,因为我目前没有办法测试我要写的内容,但我会推测一下.
I'm slightly reluctant to mention the =>NULL()
aspect as I have no current means of testing what I'm about to write, but I'll speculate.
如果没有 =>NULL()
默认初始化,指针组件具有未定义的关联状态.这意味着,当你这样做时
Without the =>NULL()
default initialization the pointer component has undefined association status. This means, that when you do
b1=TCoordinate(1.0_8,1.0_8)
有趣的事情发生了.
作为分配的一部分,b1
在进入 TCoordinateAssignment
时完成.最终确定涉及使用未定义关联状态的指针调用关联
.这是不允许的(结果可能会出现任何结果).
As part of the assignment b1
is finalized on entry to TCoordinateAssignment
. The finalization involves calling associated
with the pointer which is of undefined association status. This is not allowed (with the consequence that any result could come about).
这篇关于尽管完成了派生类型的 Fortran 数组和内存泄漏的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!