* move_alloc for types holding allocatable members
@ 2015-10-08 16:18 Alberto Luaces
2015-10-08 17:57 ` Steve Kargl
2015-10-08 19:35 ` Anton Shterenlikht
0 siblings, 2 replies; 6+ messages in thread
From: Alberto Luaces @ 2015-10-08 16:18 UTC (permalink / raw)
To: fortran
Hello,
I am investigating a memory leak involving "move_alloc" and data types
having allocatable members themselves.
It seems that after a move_alloc call over an array, the allocatable
members of the types that the array is holding are not synchronized, and
thus a leak happens when the array is eventually deallocated.
I have a test case, but had no luck when trying to find similar issues
in the bug tracker. Is this a known problem (gfortran 5.2.1)?
Thanks,
Alberto
--8<---------------cut here---------------start------------->8---
module alloctest
type myallocatable
integer, allocatable:: i(:)
end type myallocatable
contains
subroutine f(num, array)
implicit none
integer, intent(in) :: num
integer :: i
type(myallocatable):: array(:)
do i = 1, num
allocate(array(i)%i(5))
end do
end subroutine f
end module alloctest
program name
use alloctest
implicit none
type(myallocatable), allocatable:: myarray(:), mytemp(:)
allocate(myarray(7))
call f(size(myarray), myarray)
myarray(3)%i = 6
print *, myarray(3)%i
allocate(mytemp(20))
call move_alloc(mytemp, myarray)
print *, myarray(3)%i
deallocate(myarray)
end program name
--8<---------------cut here---------------end--------------->8---
--
Alberto
^ permalink raw reply [flat|nested] 6+ messages in thread
* Re: move_alloc for types holding allocatable members
2015-10-08 16:18 move_alloc for types holding allocatable members Alberto Luaces
@ 2015-10-08 17:57 ` Steve Kargl
2015-10-08 19:06 ` Alberto Luaces
2015-10-08 19:35 ` Anton Shterenlikht
1 sibling, 1 reply; 6+ messages in thread
From: Steve Kargl @ 2015-10-08 17:57 UTC (permalink / raw)
To: Alberto Luaces; +Cc: fortran
On Thu, Oct 08, 2015 at 06:18:19PM +0200, Alberto Luaces wrote:
>
> allocate(mytemp(20))
> call move_alloc(mytemp, myarray)
>
What are you expecting to happen here?
--
Steve
^ permalink raw reply [flat|nested] 6+ messages in thread
* Re: move_alloc for types holding allocatable members
2015-10-08 17:57 ` Steve Kargl
@ 2015-10-08 19:06 ` Alberto Luaces
2015-10-08 20:34 ` Steve Kargl
0 siblings, 1 reply; 6+ messages in thread
From: Alberto Luaces @ 2015-10-08 19:06 UTC (permalink / raw)
To: fortran
Steve Kargl writes:
> On Thu, Oct 08, 2015 at 06:18:19PM +0200, Alberto Luaces wrote:
>>
>> allocate(mytemp(20))
>> call move_alloc(mytemp, myarray)
>>
>
> What are you expecting to happen here?
Hi, Steve. I wanted to grow the array to 20 elements. My real code
works that way, since the length is not known beforehand, and it usually
gets bigger. Did I reverse the arguments?
--
Alberto
^ permalink raw reply [flat|nested] 6+ messages in thread
* Re: move_alloc for types holding allocatable members
2015-10-08 19:06 ` Alberto Luaces
@ 2015-10-08 20:34 ` Steve Kargl
2015-10-09 8:23 ` Alberto Luaces
0 siblings, 1 reply; 6+ messages in thread
From: Steve Kargl @ 2015-10-08 20:34 UTC (permalink / raw)
To: Alberto Luaces; +Cc: fortran
On Thu, Oct 08, 2015 at 09:06:42PM +0200, Alberto Luaces wrote:
> Steve Kargl writes:
>
> > On Thu, Oct 08, 2015 at 06:18:19PM +0200, Alberto Luaces wrote:
> >>
> >> allocate(mytemp(20))
> >> call move_alloc(mytemp, myarray)
> >>
> >
> > What are you expecting to happen here?
>
> Hi, Steve. I wanted to grow the array to 20 elements. My real code
> works that way, since the length is not known beforehand, and it usually
> gets bigger. Did I reverse the arguments?
>
13.7.82 MOVE_ALLOC (FROM, TO)
Description. Moves an allocation from one allocatable object to another.
FROM may be of any type and rank. It shall be allocatable. It is an
INTENT(INOUT) argument.
TO shall be type compatible (5.1.1.2) with FROM and have the same
rank. It shall be allocatable. It shall be polymorphic if FROM
is polymorphic. It is an INTENT(OUT) argument. Each nondeferred
parameter of the declared type of TO shall have the same value
as the corresponding parameter of the declared type of FROM.
The allocation status of TO becomes unallocated if FROM is unallocated
on entry to MOVE_ALLOC. Otherwise, TO becomes allocated with dynamic
type, type parameters, array bounds, and value identical to those that
FROM had on entry to MOVE ALLOC.
If TO has the TARGET attribute, any pointer associated with FROM on
entry to MOVE_ALLOC becomes correspondingly associated with TO. If
TO does not have the TARGET attribute, the pointer association status
of any pointer associated with FROM on entry becomes undefined.
The allocation status of FROM becomes unallocated.
Note that TO is INTENT(OUT). So,
The INTENT (OUT) attribute for a nonpointer dummy argument specifies
that it shall be defined before a reference to the dummy argument is
made within the procedure and any actual argument that becomes
associated with such a dummy argument shall be definable. On invocation
of the procedure, such a dummy argument becomes undefined except for
components of an object of derived type for which default initialization
has been specified.
My interpretation, which may be incorrect, is that
(1) myarray becomes undefined on entry into MOVE_ALLOC. I'm too
lazy at the moment to see if undefineness means proper deallocation
of an allocatable entity.
(2) mytemp is allocated to size 20, but the component 'i' of each entity
has not been allocated and are undefined. So, your call to MOVE_ALLOC
is invalid code because it is going to (implicitly) involve un-
allocated entities.
So, yes, I believe you have the arguments backwards.
--
Steve
^ permalink raw reply [flat|nested] 6+ messages in thread
* Re: move_alloc for types holding allocatable members
2015-10-08 20:34 ` Steve Kargl
@ 2015-10-09 8:23 ` Alberto Luaces
0 siblings, 0 replies; 6+ messages in thread
From: Alberto Luaces @ 2015-10-09 8:23 UTC (permalink / raw)
To: fortran
Steve Kargl writes:
> So, yes, I believe you have the arguments backwards.
Of course you are right. It was a bug on my code, sorry about that and
thank you for your throughout analysis.
I have corrected the example code to mimic what our production code
does. I also forgot copying old data to the new array before the call
to move_alloc.
After growing the array from 7 elements (OLDSIZE) to 20 (NEWSIZE), and
then deallocating, valgrind warns me about 7 leaked blocks. They are
likely the allocations for the first 7 sub-elements.
I have checked this example on a different compiler and shows no leaks.
That is what led me to think that it might be a bug.
--8<---------------cut here---------------start------------->8---
module alloctest
type myallocatable
integer, allocatable:: i(:)
end type myallocatable
contains
subroutine f(num, array)
implicit none
integer, intent(in) :: num
integer :: i
type(myallocatable):: array(:)
do i = 1, num
allocate(array(i)%i(5))
end do
end subroutine f
end module alloctest
program name
use alloctest
implicit none
type(myallocatable), allocatable:: myarray(:), mytemp(:)
integer, parameter:: OLDSIZE = 7, NEWSIZE = 20
allocate(myarray(OLDSIZE))
call f(size(myarray), myarray)
allocate(mytemp(NEWSIZE))
mytemp(1:OLDSIZE) = myarray
call move_alloc(mytemp, myarray)
deallocate(myarray)
end program name
--8<---------------cut here---------------end--------------->8---
==9262== Memcheck, a memory error detector
==9262== Copyright (C) 2002-2015, and GNU GPL'd, by Julian Seward et al.
==9262== Using Valgrind-3.11.0 and LibVEX; rerun with -h for copyright info
==9262== Command: ./ra
==9262==
==9262==
==9262== HEAP SUMMARY:
==9262== in use at exit: 140 bytes in 7 blocks
==9262== total heap usage: 40 allocs, 33 frees, 13,817 bytes allocated
==9262==
==9262== 140 bytes in 7 blocks are definitely lost in loss record 1 of 1
==9262== at 0x4C28C4F: malloc (vg_replace_malloc.c:299)
==9262== by 0x400985: __alloctest_MOD_f (in /testsFortran/ra)
==9262== by 0x400DBB: MAIN__ (in /testsFortran/ra)
==9262== by 0x401433: main (in /testsFortran/ra)
==9262==
==9262== LEAK SUMMARY:
==9262== definitely lost: 140 bytes in 7 blocks
==9262== indirectly lost: 0 bytes in 0 blocks
==9262== possibly lost: 0 bytes in 0 blocks
==9262== still reachable: 0 bytes in 0 blocks
==9262== suppressed: 0 bytes in 0 blocks
==9262==
==9262== For counts of detected and suppressed errors, rerun with: -v
==9262== ERROR SUMMARY: 1 errors from 1 contexts (suppressed: 0 from 0)
--
Alberto
^ permalink raw reply [flat|nested] 6+ messages in thread
* Re: move_alloc for types holding allocatable members
2015-10-08 16:18 move_alloc for types holding allocatable members Alberto Luaces
2015-10-08 17:57 ` Steve Kargl
@ 2015-10-08 19:35 ` Anton Shterenlikht
1 sibling, 0 replies; 6+ messages in thread
From: Anton Shterenlikht @ 2015-10-08 19:35 UTC (permalink / raw)
To: aluaces, fortran
>program name
> use alloctest
> implicit none
> type(myallocatable), allocatable:: myarray(:), mytemp(:)
>
> allocate(myarray(7))
> call f(size(myarray), myarray)
>
> myarray(3)%i = 6
> print *, myarray(3)%i
>
> allocate(mytemp(20))
> call move_alloc(mytemp, myarray)
>
> print *, myarray(3)%i
>
> deallocate(myarray)
>end program name
Perhaps like this:
rat> cat z.f90
program name
use alloctest
implicit none
integer :: ind
type(myallocatable), allocatable:: myarray(:), mytemp(:)
allocate( myarray(7) )
call f( size( myarray ), myarray )
myarray(3)%i = 6
print *, myarray(3)%i
call move_alloc( myarray, mytemp )
print *, mytemp(3)%i
deallocate( mytemp )
end program name
rat> ./a.out
6 6 6 6 6
6 6 6 6 6
Anton
^ permalink raw reply [flat|nested] 6+ messages in thread
end of thread, other threads:[~2015-10-09 8:23 UTC | newest]
Thread overview: 6+ messages (download: mbox.gz / follow: Atom feed)
-- links below jump to the message on this page --
2015-10-08 16:18 move_alloc for types holding allocatable members Alberto Luaces
2015-10-08 17:57 ` Steve Kargl
2015-10-08 19:06 ` Alberto Luaces
2015-10-08 20:34 ` Steve Kargl
2015-10-09 8:23 ` Alberto Luaces
2015-10-08 19:35 ` Anton Shterenlikht
This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox;
as well as URLs for read-only IMAP folder(s) and NNTP newsgroup(s).