当我通过gfortran和Valgrind或ifort和Intel Inspector运行下面的代码时,第一次检测到对象的过程set
时会检测到内存泄漏。第二次似乎没有导致任何内存泄漏。那是为什么?
module mymod
implicit none
type mytype
integer, pointer :: intArray(:) => null()
contains
procedure :: set
end type mytype
contains
subroutine set(this, intArray)
class(mytype), intent(inout) :: this
integer, intent(in) :: intArray(:)
integer n
n = size(intArray)
nullify(this%intArray)
allocate(this%intArray(n)) !line 20
this%intArray = intArray
end subroutine set
end module mymod
program main
use mymod !line 28
implicit none
type(mytype) :: myvar
call myvar%set((/1,2,3/)) !line 33
print *, myvar%intArray
call myvar%set((/9,8,7,6,5/))
print *, myvar%intArray
end program main
Valgrind报告以下内存泄漏:
==6669== 12 bytes in 1 blocks are definitely lost in loss record 1 of 2
==6669== at 0x402BB7A: malloc (in /usr/lib/valgrind/vgpreload_memcheck-x86-linux.so)
==6669== by 0x804886A: __mymod_MOD_set (main.f90:20)
==6669== by 0x8048988: MAIN__ (main.f90:33)
==6669== by 0x8048ADC: main (main.f90:28)
有关行号,请参阅代码中的注释。
答案 0 :(得分:3)
第一次调用set绑定时,您将分配一个“anonymous”size three数组来存储提供的整数。同时你将intArray
组件关联到指向新分配的数组 - 当你在ALLOCATE指针时,语句在概念上做了两件事。
第二次调用set绑定时,在重复指针分配过程之前,先断开intArray
组件与NULLIFY语句分配之间的关联。
Nullify不(必然)解除分配。你的程序基本上没有跟踪三级数组的初始分配。三个整数,通常每个整数四个字节 - 丢失十二个字节。
如果使用指针,一般原则是对于代码路径中遇到的每个ALLOCATE,您需要在后面的代码路径中使用匹配的DEALLOCATE。
(在Fortran 2003或更高版本中(这是你正在使用的,因为你有类型绑定的过程),你应该只使用指针和指针组件,如果你实际上指向它们。如果你真的只是使用指针作为“值”,那么你应该使用可分配的变量或组件。)
答案 1 :(得分:2)
泄漏实际上发生在set
的第二次调用上。您nullify
指针,但它已经关联,内容丢失。因此,您必须先调用deallocate
并使用associated()
测试关联状态。