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

Why memory leak?

S-Poulsen
Novice
259 Views

I am puzzled that the following test program is causing memory leak:

program memory_leak
    
    implicit none
    
    real, dimension(1:3) :: x_vec
    integer :: m, n
    
    do m=1, 10000
        print*, m
        do n=1, 10000
            x_vec = normalize_with_allocatable([1.0, 2.0, 3.0])
        end do
    end do
    
contains
    
    function normalize_with_allocatable(x_vec)
        real, dimension(:), intent(in) :: x_vec
        real, dimension(:), allocatable :: normalize_with_allocatable
        normalize_with_allocatable = x_vec/norm2(x_vec)
    end function
    
    function normalize_with_fixed_size(x_vec)
        real, dimension(:), intent(in) :: x_vec
        real, dimension(1:size(x_vec)) :: normalize_with_fixed_size
        normalize_with_fixed_size = x_vec/norm2(x_vec)
    end function
    
end program

If the function normalize_with_fixed_size is used instead, there is no memory leak. Hence, the leakage seems to be related to the allocation. Still, I am understanding that variables are automatically deallocated in Fortran, which make me think there should be no memory leak in this test program, but apparently I am wrong.

I have tried the test program using ifx 2024.2.1 and ifort 2021.13.1 on Windows and Linux.

 

Labels (1)
1 Solution
jimdempseyatthecove
Honored Contributor III
237 Views

I believe you have an error in programming that was not caught by the compiler (try adding warn all).

In function normalize_with_allocatable you declare the return value to be allocatable...

... yet the use of the function call return, is targeted to a non-allocatable array.

  

    ...
    real, dimension(1:3) :: x_vec
    ...
    x_vec = normalize_with_allocatable(...)

Jim Dempsey

View solution in original post

6 Replies
jimdempseyatthecove
Honored Contributor III
238 Views

I believe you have an error in programming that was not caught by the compiler (try adding warn all).

In function normalize_with_allocatable you declare the return value to be allocatable...

... yet the use of the function call return, is targeted to a non-allocatable array.

  

    ...
    real, dimension(1:3) :: x_vec
    ...
    x_vec = normalize_with_allocatable(...)

Jim Dempsey

S-Poulsen
Novice
220 Views

Thank you, you are right, making the x_vec variable allocatable removes the memory leak. Nevertheless, the warn all flag did not report any warnings.

0 Kudos
jimdempseyatthecove
Honored Contributor III
152 Views

I agree that this is a bug.

Because the function was a contained procedure, the interface was known to the compiler. The call with the result stored in a non-allocatable (in this case) should have been caught at compile time.

 

FWIW there are other problem reports with functions returning allocatable arguments. Not sure if your case is related.

 

If you make the procedure a subroutine there should be no issue.

 

Jim

 

0 Kudos
IanH
Honored Contributor II
118 Views

You can store an allocatable function result in a non-allocatable variable - you just need to make sure that the shape (and perhaps length parameters, etc) matches.  That requires the calling context to know those things ahead of the call, which means the function can know those things when it is invoked, which kind of defeats the point of the function result being allocatable, but so be it.

This is just a compiler bug, failing to free the memory associated with the allocatable function result.  If you inspect the assembly for the main program, you'll not see a reference to something like for_dealloc_allocatable or its siblings.

0 Kudos
jimdempseyatthecove
Honored Contributor III
74 Views

@IanH  How can the function know the shape/lengths of the return argument when the return to argument (not result argument being declared as allocatable) is not allocatable?

conversely

How can the compiler know the shape/lengths of the return argument at compile time (for comparison to the lhs) when it only has the interface to the function but not the algorithm for producing the shape/lengths of the allocatable result? Note, this can be caught at runtime, provided runtime checks are enabled.

The above concerns are independent of the memory leak issue.

 

Jim Dempsey

0 Kudos
IanH
Honored Contributor II
37 Views

I'm talking about the possibility of information flow in the program.  This is not [necessarily] a compile time question, nor a question for the compiler.

The rules of the language require that if the variable in the calling context being assigned the result of the function call is not allocatable (x_vec in the main program - let's call this the receiving variable), then its shape must match (be conformable) with whatever the function spits out (F2023 10.2.1.2p1 (3)).  That's a requirement the programmer needs to ensure is met. 

The programmer might figure out the [logic for the] required shape by inspecting the source of the function, by asking a friend, reading documentation, putting some complicated calculation in the main program, whatever - it is their problem to get it right at execution time, ahead of the function being invoked.  If they have gone to all the effort to ensure that the receiving variable is the right shape, then it is trivial to pass that shape to a rewritten form of that function, so that the function knows it as soon as it is invoked, and can therefore use something like an non-allocatable automatic result variable. 

This is pretty much the case for the normalize_with_fixed_size function - it is told the shape of its return variable via the shape of its dummy argument (at runtime, it ain't "fixed", as that is usually taken to mean - normalize_with_explicit_size would be a better description).

(A good compiler/Fortran processor implementation might check that the shape matches at runtime, and if they don't match let the programmer know they have made a mistake, but that's a different discussion.)

0 Kudos
Reply