Intel® Fortran Compiler
Build applications that can scale for the future with optimized code designed for Intel® Xeon® and compatible processors.
29001 Discussions

Possible memory leak when ALLOCATABLE array is used in TYPE definition

Jon_D
New Contributor II
423 Views
I have the following program to test a possible memory leak:

MODULE MyMod

TYPE MyType
REAL(8),ALLOCATABLE :: a(:)
END TYPE MyType
TYPE(MyType),ALLOCATABLE,TARGET,SAVE :: ArrayMyType(:)
INTEGER,SAVE :: dim


CONTAINS


SUBROUTINE Init(n,d)
INTEGER :: n,d(n)

dim = n
ALLOCATE (ArrayMyType(n))
DO i=1,n
ALLOCATE (ArrayMyType(i)%a(d(i)))
END DO

END SUBROUTINE Init

END MODULE


SUBROUTINE Test()
USE MyMod
TYPE(MyType)::p(dim)

p=ArrayMyType

END SUBROUTINE Test


PROGRAM Main
USE MyMod
INTEGER::d(2000)

d=5
CALL Init(2000,d)
DO i=1,1000
CALL Test()
END DO

END


I execute this program and watch the memory usage in task manager soar up to 206 Mbytes. Then I convert the variable "p" in SUBROUTINE Test() into a pointer:

SUBROUTINE Test()
USE MyMod
TYPE(MyType),POINTER::p(:)

p=>ArrayMyType

END SUBROUTINE Test

When the program is executed, memory usage stabilizes around 2.5 Mbytes. Similarly when I change the type definition in the MODULE MyMod to

TYPE MyType
REAL(8),POINTER :: a(:)
END TYPE MyType

I get no memory leaks with two different definitions of p in the subroutine.

Is this the expected behavior or is there a bug in the compiler? The whole reason I got into this testing is because F2003 supports ALLOCATABLE arrays as UDT components and I have read that using ALLOCATABLE arrays produces memory-wise secure (i.e. less likely to get memory leaks) code than using POINTERs. But this test shows the opposite.

I am using IVF 10.1.011 with VS2005.

Any comments will be much appreciated.

Jon

0 Kudos
3 Replies
jimdempseyatthecove
Honored Contributor III
423 Views

Jon,

When using

TYPE(MyType)::p(dim)
p=ArrayMyType

You create a second copy of ArrayMyType, either on stack or on heap dependent on option switches.
And third copy while deleting second copy of ArrayMyType.
And fourth copy...

When using

TYPE(MyType),POINTER::p(:)
p=>ArrayMyType

You create a descriptor for p(:), either on stack or on heap dependent on option switches. The descriptor is fairly small.
The second and later calls reused the descriptor and require no allocations

Under Windows the heap manager performs a lazy free operation. This means that when the array is deallocated (reallocated) that the deallocation is deferred (to protect against use of deallocated buffer) and the end effect is for the allocations to incrementally traverse the free virtual address space. IOW the (return to) heap is similar to a ring buffer at least up until some number/amount of returns are made then the memory gets reused.

If you use the Page File usage as an indicator of memory leak you will get a false reading since that will also include the memory returned as well as the memory currently allocated (for program and data).

Jim Dempsey

0 Kudos
Jon_D
New Contributor II
423 Views
Jim,

Thank you for the reply. Pardon my ignorance but most of your explanation was over my head. What I understand from your reply is that Windows Task Manager (I used the "Mem Usage" column to monitor the memory) is not a reliable way to check for memory leaks. I vaguely remember reading similar discussions on this forum and I think it was mentioned that there is not a good utility out there to check for memory leaks easily.

So, I assume that I can go ahead and use ALLOCATABLE arrays in TYPE definitions.

Thanks,
Jon
0 Kudos
jimdempseyatthecove
Honored Contributor III
423 Views

Jon,

You can search Microsoft's MSDN articles on memory leaks. I took a look myself and it seams as if the easy things you would like to do are cleaverly hidden from the index. e.g.

What is the total of the current heap(s) allocations
What was the largest total of the heap(s) allocations

Jim Dempsey

0 Kudos
Reply