尽管最终确定,但派生类型的 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.
推荐答案
在对定稿过程的描述中我们看到 (Fortran 2008, 4.5.6.2)
In the description of the finalization process we see (Fortran 2008, 4.5.6.2)
如果实体的动态类型有一个最终子例程,其伪参数与被终结的实体具有相同的类型参数和等级,则以实体作为实际参数调用它.否则,如果存在一个基本的最终子程序,其虚拟参数具有相同的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屋!