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

Memory leak in FORTRAN format with variable string length

rakkota
Novice
1,339 Views

Hi,

I am experiencing a memory leak of ~1MB in a subroutine if I am using the following write like statement inside:

    write(*,10)(line(j),j=1,var)
10  format(1x,<var>a1)

where var is variable computed at runtime. Is this a known issue?

I am using ifort 13.1.3.198 Build 20130607 under Windows.

Rak

0 Kudos
10 Replies
Steven_L_Intel1
Employee
1,339 Views

Would you please provide a small but complete example demonstrating this? Also, please try the current version 15.0.2 if you can.

0 Kudos
FortranFan
Honored Contributor III
1,339 Views

rakkota wrote:

..

I am using ifort 13.1.3.198 Build 20130607 under Windows.

Rak

Is it possible for you to upgrade to the latest version?  While it is possible the version you're using and some subsequent versions may have memory leaks with WRITE operations (I'm not sure, but I do recall running into such problems with internal files), I have not noticed issues with WRITE and memory leaks in the current compiler 2015, update 2 version.

By the way, you may know the use of <var> in the FORMAT statement is a compiler extension and not standard-conforming.  See this thread, Quote #18 by Steve Lionel: https://software.intel.com/en-us/forums/topic/542686.

0 Kudos
mecej4
Honored Contributor III
1,339 Views

Here is a reproducer. I put the VFEs in a subroutine to localize the reported location of the memory leak. I used IFort 15.0.2 - 32 bit. Changing the upper limit of the DO loop to 540 did not change the reported size of the leak,

No problem was reported when I used the 64-bit compiler.

program vfex
call sub()        ! memory leak of 1056768 bytes reported by Inspector XE
end program

subroutine sub()
implicit none
integer :: i,j,nvar
character(1) :: lin(255)
character(255) :: olin
do i=1,255
   lin(i)=char(mod(i*257+13,255))
end do
do i=513,767
   nvar=i-512
100 format(<nvar>A1)
   write(olin,100)(lin(j),j=nvar,1,-1)
end do
end subroutine sub

 

0 Kudos
FortranFan
Honored Contributor III
1,339 Views

mecej4 wrote:

Here is a reproducer. ..

Interesting, I wonder if it is a false positive by Intel Inspector.

Anyways, one can retry with line 15 replaced with standard-conforming

100 format(*(A1))

 

0 Kudos
Steven_L_Intel1
Employee
1,339 Views

Thanks, we'll check this out.

0 Kudos
rakkota
Novice
1,339 Views

Hi,

More updates on the leak: it leaks only at the first time it calls the function, subsequent calls do not increase the leak. If the function is in an executable, 1MB might not be the end of the world. Our problem is that this function is part of a dll which is loaded/unloaded many times, which adds up fast.

I am using ProcessExplorer to follow the leak (Private Bytes column).

It seems that the following similar code does not leak:

     integer*4, parameter :: MATN_ = 10
     write(*,10)(line(j),j=1,MATN_)
  10 format(1x,<MATN_>a1)

Rak

0 Kudos
rakkota
Novice
1,339 Views

Hi,

More updates on the leak: it leaks only at the first time it calls the function, subsequent calls do not increase the leak. If the function is in an executable, 1MB might not be the end of the world. Our problem is that this function is part of a dll which is loaded/unloaded many times, which adds up fast.

I am using ProcessExplorer to follow the leak (Private Bytes column).

It seems that the following similar code does not leak:

     integer*4, parameter :: MATN_ = 10
     write(*,10)(line(j),j=1,MATN_)
  10 format(1x,<MATN_>a1)

Rak

0 Kudos
Steven_L_Intel1
Employee
1,339 Views

Thanks - I have escalated this as issue DPD200368141.

0 Kudos
rakkota
Novice
1,339 Views

FortranFan wrote:

Quote:

Anyways, one can retry with line 15 replaced with standard-conforming
100 format(*(A1))

Thanks Lionel.
Using the standard notation *(A1) works fine in isolation, as suggested, but produces undesired output if used in conjunction with other variables. For example the following dummy code:

     subroutine myfunc()
     implicit none
     integer*4, parameter :: MATN_ = 10
     integer line(10),j,var
     data line/'a','b','c','d','e','f','g','h','i','j'/
     var=MATN_
     write(*,10)(line(j),j=1,var-2),line(2),line(3)
  10 format(1x,*(a1),1x,a1,a1)
     end subroutine myfunc    

produces at output

 abcdefghbc

while expected

 abcdefgh bc

On the other hand, the equivalent variable length construction

    write(*,10)(line(j),j=1,var-2),line(2),line(3)
10  format(1x,<var-2>(a1),1x,a1,a1)

comes in handy and produces the expected result.

Rak

 

0 Kudos
Steven_L_Intel1
Employee
1,339 Views

Investigation so far shows that this leak occurs for VFEs and if you pass a contained procedure as an argument - both create what is called a "bound procedure value" and the routine that is doing this is reserving a rather large chunk of memory for a pool and not releasing it on image exit or DLL unload. Only 12 bytes for the BPV is being allocated, but that larger pool is the leak. It's a one-time thing, but we understand the issue for DLLs.

Still, for your case if you can avoid VFEs it would be better. It is true that the unlimited repeat count isn't useful if other variables follow that need different formats. The standard-conforming approach would be something like this:

   subroutine myfunc()
   implicit none
   integer*4, parameter :: MATN_ = 10
   integer line(10),j,var
   data line/'a','b','c','d','e','f','g','h','i','j'/
   character(50) fmt
   var=MATN_
   write (fmt,'(A,I0,A)') '(1x,',var-2,'a1,1x,a1,a1)'
   write(*,fmt)(line(j),j=1,var-2),line(2),line(3)
   end subroutine myfunc    

 

0 Kudos
Reply