Google Groups no longer supports new Usenet posts or subscriptions. Historical content remains viewable.
Dismiss

memory leak in fortran?

1,328 views
Skip to first unread message

Rudra Banerjee

unread,
Jun 12, 2013, 12:11:32 PM6/12/13
to
hello friends,
I am (still) trying to learn C. in C forums, I found, they are very
serious about "memory leaks". I don't think we, in fortran, are such
particular about memory leaks. So, I was trying to understand memory
leaks in my native language, and was trying to generate a leak...and I
failed.
Program leak
Implicit None
integer,pointer :: i
integer, target :: j
integer :: k
j=15;k=10
i=>j
k=j
write(*,*)k,j,i

End Program leak

the (initial) value of k is impossible to reach, and also I have not
free'd the pointer before quit. still all blocks are free.
$ valgrind --tool=memcheck --leak-check=yes ./a.out
==27597== Memcheck, a memory error detector
==27597== Copyright (C) 2002-2012, and GNU GPL'd, by Julian Seward et
al.
==27597== Using Valgrind-3.8.1 and LibVEX; rerun with -h for copyright
info
==27597== Command: ./a.out
==27597==
15 15 15
==27597==
==27597== HEAP SUMMARY:
==27597== in use at exit: 0 bytes in 0 blocks
==27597== total heap usage: 21 allocs, 21 frees, 11,987 bytes
allocated
==27597==
==27597== All heap blocks were freed -- no leaks are possible
==27597==
==27597== For counts of detected and suppressed errors, rerun with: -v
==27597== ERROR SUMMARY: 0 errors from 0 contexts (suppressed: 2 from 2)


What I am missing? Is it possible to show leaks in such tiny program?

Ron Shepard

unread,
Jun 12, 2013, 12:33:31 PM6/12/13
to
In article <1371053492.15693.4.camel@roddur>,
Rudra Banerjee <bnrj....@gmail.com> wrote:

> What I am missing? Is it possible to show leaks in such tiny program?

Most memory leaks involve pointers. Here is a short (incomplete)
example:

integer, pointer :: i(:)
allocate( i(10) ) ! this allocates some memory.
allocate( i(20) ) ! this allocates some more memory.

The leak occurs because the original 10 integers was not deallocated
and can no longer be accessed.

This is one reason why pointers should be avoided in fortran unless
they are really necessary. There are other reasons too, related to
efficiency and low-level code optimization.

$.02 -Ron Shepard

Richard Maine

unread,
Jun 12, 2013, 12:34:18 PM6/12/13
to
Rudra Banerjee <bnrj....@gmail.com> wrote:

> So, I was trying to understand memory
> leaks in my native language, and was trying to generate a leak...and I
> failed.

That's because you never allocated any memory. You won't get memory
leaks just pointing to variables declared with the target attribute.

A memory leak doesn't relate to accessing old *VALUES* of the same
variable; It has nothing to do with values at all. It relates to
accessing memory locations. Accessing old values has nothing to do with
pointers.

A memory leak happens when you allocate some memory and then later end
up having no pointers to that allocated memory without having
deallocated it. If you never allocate any memory, the issue doesn't come
up.

Certainly it is possible to do this simply. Trivially.

do i = 1 , something
allocate(x)
end do

(x being a pointer) is about as easy as you can get. In that case,
nothing useful is ever done with x. Add stuff actually using x to taste.

--
Richard Maine
email: last name at domain . net
domain: summer-triangle

Paul van Delst

unread,
Jun 12, 2013, 3:22:49 PM6/12/13
to
Give this a go:

program test_memleak
implicit none
integer, pointer :: x(:) => NULL()
allocate(x(10))
allocate(x(20))
end program test_memleak


$ gfortran test_memleak.f90
$ valgrind a.out
==543== Memcheck, a memory error detector
==543== Copyright (C) 2002-2012, and GNU GPL'd, by Julian Seward et al.
==543== Using Valgrind-3.8.1 and LibVEX; rerun with -h for copyright info
==543== Command: a.out
==543==
==543==
==543== HEAP SUMMARY:
==543== in use at exit: 120 bytes in 2 blocks
==543== total heap usage: 18 allocs, 16 frees, 2,739 bytes allocated
==543==
==543== LEAK SUMMARY:
==543== definitely lost: 40 bytes in 1 blocks
==543== indirectly lost: 0 bytes in 0 blocks
==543== possibly lost: 0 bytes in 0 blocks
==543== still reachable: 80 bytes in 1 blocks
==543== suppressed: 0 bytes in 0 blocks
==543== Rerun with --leak-check=full to see details of leaked memory
==543==
==543== For counts of detected and suppressed errors, rerun with: -v
==543== ERROR SUMMARY: 0 errors from 0 contexts (suppressed: 6 from 6)


Or,

program test_memleak
implicit none
integer, target :: a(20)
integer, pointer :: x(:) => NULL()
allocate(x(10))
x=>a
end program test_memleak


$ gfortran test_memleak.f90
$ valgrind a.out
==987== Memcheck, a memory error detector
==987== Copyright (C) 2002-2012, and GNU GPL'd, by Julian Seward et al.
==987== Using Valgrind-3.8.1 and LibVEX; rerun with -h for copyright info
==987== Command: a.out
==987==
==987==
==987== HEAP SUMMARY:
==987== in use at exit: 40 bytes in 1 blocks
==987== total heap usage: 17 allocs, 16 frees, 2,659 bytes allocated
==987==
==987== LEAK SUMMARY:
==987== definitely lost: 40 bytes in 1 blocks
==987== indirectly lost: 0 bytes in 0 blocks
==987== possibly lost: 0 bytes in 0 blocks
==987== still reachable: 0 bytes in 0 blocks
==987== suppressed: 0 bytes in 0 blocks
==987== Rerun with --leak-check=full to see details of leaked memory
==987==
==987== For counts of detected and suppressed errors, rerun with: -v
==987== ERROR SUMMARY: 0 errors from 0 contexts (suppressed: 6 from 6)

Arjen Markus

unread,
Jun 13, 2013, 3:38:56 AM6/13/13
to
Op woensdag 12 juni 2013 18:11:32 UTC+2 schreef Rudra Banerjee het volgende:

>
> What I am missing? Is it possible to show leaks in such tiny program?

The replies so far did not include _allocatable_ variables. With allocatables
you can not get memory leaks - except if there is a pointer to such an allocatable.

Allocatables are deallocated automatically when the variable goes out of
scope (most likely when returning from a subprogram, where the allocatable
is a local variable without the save attribute).

So, in a program that does not use pointers, there is no chance of memory
leaks from the Fortran side (modulo errors in the compiler).

Since C does not have the facility of allocatables, but only of pointers,
the issue is much more important than within Fortran.

Regards,

Arjen

Anton Shterenlikht

unread,
Jun 13, 2013, 4:09:28 AM6/13/13
to
Arjen Markus <arjen.m...@gmail.com> writes:

>Since C does not have the facility of allocatables, but only of pointers,
>the issue is much more important than within Fortran.

This must be *the* major reason to favour fortran over C.
An incredible number of C, C++ programs segfault in use,
and the amount of man years debugging those is staggering.
At least this is my experience of running software
from ports on FreeBSD ia64 for the last 5 years or so.
Memory leaks, incorrect pointer casts, wrong assumptions
on the sizes of int, long int, etc. are the major culprits.

Anton

Wolfgang Kilian

unread,
Jun 13, 2013, 4:09:37 AM6/13/13
to
On 06/13/2013 09:38 AM, Arjen Markus wrote:

> [...] With allocatables
> you can not get memory leaks - except if there is a pointer to such an allocatable.

Well -- no. With a pointer to an allocatable you may get a dangling
pointer, but no memory leak.

-- Wolfgang

--
E-mail: firstnameini...@domain.de
Domain: yahoo

Rudra Banerjee

unread,
Jun 13, 2013, 4:56:40 AM6/13/13
to
Can this be explained?
(I am not challenging, just want to know. )

Arjen Markus

unread,
Jun 13, 2013, 9:22:21 AM6/13/13
to
Op donderdag 13 juni 2013 10:56:40 UTC+2 schreef Rudra Banerjee het volgende:
> Can this be explained?
>
> (I am not challenging, just want to know. )
>
>
>
> -----Original Message-----
>
> From: Ron Shepard
>
> Subject: Re: memory leak in fortran?
>
> Date: Wed, 12 Jun 2013 11:33:31 -0500
>
> Newsgroups: comp.lang.fortran
>
>
>
> This is one reason why pointers should be avoided in fortran unless
>
> they are really necessary. There are other reasons too, related to
>
> efficiency and low-level code optimization.

One of the optimisations Fortran compilers are allowed to make is that
every variable has its own memory location. So if you have an expression
that uses a variable x and just below that you have another expression that
uses x, the compiler may arrange the code in such a way that the value of x
is left in the cache.

Values in the cache are easy to access and access is fast.

Now though, consider this:

real :: y
real, target :: x
real, pointer :: p

(Somewhere in the code p => x)

p = 2.0 * x
y = 3.0 + x

If p were not a pointer, these two expressions would use the very same
value of x. But because x is a target, p can point to it, so that the
value of x may have changed from the first statement to the next. Hence,
the program has to retrieve the current value of x before the second statement
can be correctly run.

Does this help? It is just a sketch and I hope I have the details that
matter right, but that is the basic idea.

It is easy to construct other examples, like pointers to arrays: ordinary
arrays are contiguous in memory, but pointer to array sections need not be.

Warning: compilers and processors are getting smarter all the time, so do not
count on any optimisation effects to persist from one version of the compiler
to the next. Very few general rules exist with regards to optimisation. Two
which apply to Fortran:
- Make the code as clear as possible (that helps you and the compiler!)
- Do not use pointers if they can be avoided because of such optimisation issues
(but also because they make the code a bit harder to understand)

Regards,

Arjen

Regards,

Arjen

Tobias Burnus

unread,
Jun 13, 2013, 9:37:04 AM6/13/13
to
Arjen Markus wrote:
> Op donderdag 13 juni 2013 10:56:40 UTC+2 schreef Rudra Banerjee het volgende:
>> This is one reason why pointers should be avoided in fortran unless
>>
>> they are really necessary. There are other reasons too, related to
>>
>> efficiency and low-level code optimization.
>
> One of the optimisations Fortran compilers are allowed to make is that
> every variable has its own memory location. So if you have an expression
> that uses a variable x and just below that you have another expression that
> uses x, the compiler may arrange the code in such a way that the value of x
> is left in the cache.

I like the following example most - it also occurs in real-world code
(albeit embedded in larger code section and often with subscripts) and
it has a rather large effect:

subroutine sub(a, b)
real, pointer :: a(:), b(:)
a = b
end subroutine sub

If either "a" or "b" (or both) aren't a pointer (and if one is a
pointer, the other is not a TARGET), the compiler can simply do:

DO i = 1, size(a)
a(i) = b(i)
END DO

However, in this example, a temporary array is required; otherwise, one
gets a wrong result for:

ptr => ptr2(n:1:-1)
call sub(ptr, ptr2)

And temporary arrays are bad: The cost time for allocation/freeing of
the memory, they fill needlessly the cache and they cost a lot of memory
if the involved arrays are large.

There are other cases, where knowing whether two variables alias helps.
It also helps to know whether an array has strides or not. Allocatables,
explicit-size arrays and those with CONTIGUOUS attribute have no stride,
which might enable vectorization which otherwise couldn't be done.

Tobias

Gordon Sande

unread,
Jun 13, 2013, 9:54:33 AM6/13/13
to
The same example can be constructed using arguements and dummys. Fortran has
a number of rules to prevent aliasing that make the examples nonstandard.
This is really just an observation that sometimes pointers are present
in the implementation even if the programmer never uses explicit pointers.

Ian Chivers

unread,
Jun 13, 2013, 10:01:03 AM6/13/13
to
Jane and I have two small examples in our book that illustrate memory leaks.

The first is shown below.

program ch1805
implicit none
integer, pointer :: a => null(), b => null()
integer, target :: c
integer :: d

allocate (a)
allocate (b)
a = 100
b = 200
print *, a, b
c = 1
a => c
c = 2
b => c
d = a + b
print *, a, b, c, d
end program ch1805

in this case the leak is small, and would probably go unnoticed in
a larger program.

The second is shown below.

program ch1806
implicit none
integer :: allocate_status = 0
integer, parameter :: n1 = 10000000
integer, parameter :: n2 = 5
integer, dimension (:), pointer :: x
integer, dimension (1:n2), target :: y
integer :: i

do
allocate (x(1:n1),stat=allocate_status)
if (allocate_status>0) then
print *, ' allocate failed. program ends.'
stop
end if
do i = 1, n1
x(i) = i
end do
do i = 1, n2
print *, x(i)
end do
do i = 1, n2
y(i) = i*i
end do
do i = 1, n2
print *, y(i)
end do
! x now points to y
x => y ! x now points to y
do i = 1, n2
print *, x(i)
end do
! what has happened to the memory that x
! used to point to?
end do
end program ch1806

if you run this example on Linux open a second
console and type

top

before running the program.

on a windows platform try

[ctrl] + [alt] + [delete]

and start the task manage and go to the performance tab,
again before starting the program.

one compiler on Windows requires a power off!

hope this helps.

Ian Chivers

the rest of the examples are at

http://www.fortranplus.co.uk/book2_examples.html
0 new messages