Memory leaks 在Fortran中测试内存泄漏(使用pFUnit)
我已经用allocatable编写了我的第一个程序。它按预期工作。但是,真的吗?更重要的是,我如何设置一个单元测试来捕获内存泄漏 这个计划的想法是首先为我的物品清单分配一个储藏室。每次我在列表中添加一个比分配的大小多的元素时,我会加倍分配。我这样做是为了减少从旧分配内存到新分配内存的分配和后续数据复制的数量 我可能会把这件事复杂化,但我现在想花一些时间来理解其中的陷阱,而不是在项目的一两年中首先陷入陷阱 ode是在linux上使用gfortran 8.3.0编译的。以及使用PF4.1单元。下面的代码是仅测试分配部分的摘录 这是我的测试计划:Memory leaks 在Fortran中测试内存泄漏(使用pFUnit),memory-leaks,fortran,gfortran,Memory Leaks,Fortran,Gfortran,我已经用allocatable编写了我的第一个程序。它按预期工作。但是,真的吗?更重要的是,我如何设置一个单元测试来捕获内存泄漏 这个计划的想法是首先为我的物品清单分配一个储藏室。每次我在列表中添加一个比分配的大小多的元素时,我会加倍分配。我这样做是为了减少从旧分配内存到新分配内存的分配和后续数据复制的数量 我可能会把这件事复杂化,但我现在想花一些时间来理解其中的陷阱,而不是在项目的一两年中首先陷入陷阱 ode是在linux上使用gfortran 8.3.0编译的。以及使用PF4.1单元。下面的
program test_realloc
use class_test_malloc
integer :: i
real :: x, y
type(tmalloc) :: myobject
call myobject%initialize()
do i=1, 100
x = i * i
y = sqrt(x)
call myobject%add_nbcell(i, x, y)
end do
call myobject%dump()
end program test_realloc
数组_重新分配。f:
!
! Simple test to see if my understanding of dynamicly allocation
! of arrays is correct.
!
module class_test_malloc
use testinglistobj
implicit none
type tmalloc
integer :: numnbcells, maxnbcells
type(listobj), allocatable :: nbcells(:)
contains
procedure, public :: initialize => init
procedure, public :: add_nbcell ! Might be private?
procedure, private :: expand_nbcells
procedure, public :: dump
end type tmalloc
contains
subroutine init(this)
class(tmalloc), intent(inout) :: this
this%numnbcells = 0
this%maxnbcells = 4
allocate (this%nbcells(this%maxnbcells))
end subroutine init
subroutine add_nbcell(this, idx, x, y)
class(tmalloc), intent(inout) :: this
integer, intent(in) :: idx
real, intent(in) :: x, y
type(listobj) :: nbcell
if(this%numnbcells .eq. this%maxnbcells) then
call this%expand_nbcells()
print *,"Expanding"
endif
this%numnbcells = this%numnbcells + 1
nbcell%idx = idx
nbcell%x = x
nbcell%y = y
this%nbcells(this%numnbcells) = nbcell
print *,"Adding"
end subroutine add_nbcell
subroutine expand_nbcells(this)
class(tmalloc), intent(inout) :: this
type(listobj), allocatable :: tmpnbcells(:)
integer :: size
size = this%maxnbcells *2
allocate (tmpnbcells(size))
tmpnbcells(1:this%maxnbcells) = this%nbcells
call move_alloc( from=tmpnbcells, to=this%nbcells)
this%maxnbcells = size
end subroutine
subroutine dump(this)
class(tmalloc), intent(inout) :: this
integer :: i
do i=1, this%numnbcells
print*, this%nbcells(i)%x, this%nbcells(i)%y
end do
end subroutine
end module
listobj.f:
module testinglistobj
type listobj
integer :: idx
real :: x
real :: y
end type
end module testinglistobj
此代码不会导致任何内存泄漏。原因是,这是理解可分配数组的基础,在Fortran 95以后的版本中,要求不带save属性的可分配数组在超出范围时自动取消分配。这样做的净结果是这样的阵列不可能出现内存泄漏。这就是为什么您更喜欢可分配数组而不是指针的一个很好的原因。相关的是一般的软件工程原理,即尽可能限制变量的范围,以便数组在内存中的时间尽可能短
请注意,这并不意味着您永远不应该取消分配它们,因为数组可能在实际使用后很长时间仍保留在作用域中。在这里,可以使用手动解除分配。但这不是内存泄漏。一般来说,如果您使用的是可分配对象,并且存在内存泄漏,那是编译器编写者的错,而不是您的错。原则上没有问题。你有具体的理由担心吗?如果是这样,有一些工具可以提供帮助[首先,gfortran的-Wall和-fcheck=all标志,后者不适用于生产运行,因为它支持运行时检查,valgrind也可能有帮助]。有什么理由提到PFU吗?