From: Gib Bogle on
I am still trying to get to grips with how one should copy derived types that contain allocatable
arrays. The test program below, when compiled with IVF 10.1, displays the cdata array contents
correctly, but gives an access violation in the deallocation step. If I neglect the deallocation
there are no error messages. When compiled on IBM Linux (with xlf95_r) it runs without errors. But
running my real program, in which I am presumably doing something wrong, on the IBM machine there is
no error until the deallocation step, which is carried out exactly as in the code below, and then I
get a multitude of error messages like

glibc detected *** double free or corruption (!prev): 0x100a0220
and
glibc detected *** corrupted double-linked list: 0x1009db18


Is it OK to do

cell2(i) = cell1(i)

when cell2(i)%cdata has not been allocated, or do I first need to ensure that %cdata is allocated?


!----------------------------------------------------------------
program main
integer :: csize(2) = (/10,100/)
integer :: k, i
type cell_type
integer :: ID
real, allocatable :: cdata(:)
end type
type(cell_type), allocatable :: cell1(:),cell2(:)

allocate(cell1(2))
allocate(cell2(2))

do i = 1,2
allocate(cell1(i)%cdata(csize(i)))
do k = 1,csize(i)
cell1(i)%cdata(k) = k
enddo
enddo

do i = 1,2
cell2(i) = cell1(i) ! cell2(i)%cdata not allocated
write(*,*) cell2(i)%cdata
enddo

do i = 1,2
do k = 1,csize(i)
if (allocated(cell1(i)%cdata)) then
deallocate(cell1(i)%cdata)
endif
enddo
if (allocated(cell1)) then
deallocate(cell1)
endif
enddo
do i = 1,2
do k = 1,csize(i)
if (allocated(cell2(i)%cdata)) then
deallocate(cell2(i)%cdata)
endif
enddo
if (allocated(cell2)) then
deallocate(cell2)
endif
enddo

end
------------ And now a word from our sponsor ------------------
Want to have instant messaging, and chat rooms, and discussion
groups for your local users or business, you need dbabble!
-- See http://netwinsite.com/sponsor/sponsor_dbabble.htm ----
From: Gib Bogle on
I must be more tired than I thought. The code I posted previously is obviously wrong, in a couple
of embarrassing ways, and the reason for the access violation is clear. What I meant to do is shown
below. This code executes fine. I thought I was on the scent of the bug in my real program, but I
was confused. The interesting thing (to me) here is that the assignment cell2(i) = cell1(i) has the
effect of allocating cell2(i)%cdata. Should this be obvious?

program main
integer :: csize(2) = (/10,100/)
integer :: k, i
type cell_type
integer :: ID
real, allocatable :: cdata(:)
end type
type(cell_type), allocatable :: cell1(:),cell2(:)

allocate(cell1(2))
allocate(cell2(2))

do i = 1,2
allocate(cell1(i)%cdata(csize(i)))
do k = 1,csize(i)
cell1(i)%cdata(k) = k
enddo
enddo

do i = 1,2
cell2(i) = cell1(i) ! cell2(i)%cdata not allocated before this
write(*,*) cell2(i)%cdata
enddo

do i = 1,2
if (allocated(cell1(i)%cdata)) then
deallocate(cell1(i)%cdata)
endif
enddo
if (allocated(cell1)) then
deallocate(cell1)
endif
do i = 1,2
if (allocated(cell2(i)%cdata)) then
write(*,*) 'deallocate cell2(i)%cdata: ',i
deallocate(cell2(i)%cdata)
endif
enddo
if (allocated(cell2)) then
deallocate(cell2)
endif

end
From: James Van Buskirk on
"Gib Bogle" <g.bogle(a)auckland.no.spam.ac.nz> wrote in message
news:481fd818$1(a)news.auckland.ac.nz...

> do i = 1,2
> do k = 1,csize(i)
> if (allocated(cell1(i)%cdata)) then
> deallocate(cell1(i)%cdata)
> endif
> enddo
> if (allocated(cell1)) then
> deallocate(cell1)
> endif
> enddo

Your problems start at the above loop. Consider that for each
value of i, there is only one cell1(i)*cdata array. Now you are
contemplating deallocating this array 10 or 100 times in the k
loop, but you are saved by the fact that you check for allocation
status before deallocating. You are not so lucky regarding the
consequences of deallocation of cell1 later in the loop, however.
Consider that on the first trip through the i loop, cell1 was
allocated, so you checked this, then deallocated it. On the
second trip through the i loop, your program should die when
you check whether cell1(i)%cdata is allocated because there is
no cell1(i)%cdata because there is no cell1(i) because you
deallocated cell1 on the first trip through the loop. You
might more easily have replaced the whole i loop with:

if(allocated(cell1)) deallocate(cell1)

Because that automatically deallocates its allocatable components.

> do i = 1,2
> do k = 1,csize(i)
> if (allocated(cell2(i)%cdata)) then
> deallocate(cell2(i)%cdata)
> endif
> enddo
> if (allocated(cell2)) then
> deallocate(cell2)
> endif
> enddo

See comments for other deallocation loop.

--
write(*,*) transfer((/17.392111325966148d0,6.5794487871554595D-85, &
6.0134700243160014d-154/),(/'x'/)); end


From: Gib Bogle on
Please forgive me for responding to my own posts.

I made csize big: csize(2) = (/1000000,100000000/), put a do loop around the whole program, and
experimented with allocating/not allocating cell2(i)%cdata in advance of assigning values to it. I
have convinced myself that there is no memory leakage. It seems that when the derived-type
variables cell2(i) and cell1(i) are equated the allocatable component cell2(i)%cdata is allocated if
not previously allocated, and if it was already allocated it is effectively resized and any unused
memory is deallocated. In other words the compiler does what you'd want it to do.

Probably everyone else already knew this.
------------ And now a word from our sponsor ---------------------
For a secure high performance FTP using SSL/TLS encryption
upgrade to SurgeFTP
---- See http://netwinsite.com/sponsor/sponsor_surgeftp.htm ----
From: James Van Buskirk on
"Gib Bogle" <g.bogle(a)auckland.no.spam.ac.nz> wrote in message
news:481ff61f$1(a)news.auckland.ac.nz...

> was confused. The interesting thing (to me) here is that the assignment
> cell2(i) = cell1(i) has the effect of allocating cell2(i)%cdata. Should
> this be obvious?

Yes, that's the way allocatable components are supposed to work.
In fact, you could have simply said:

cell2 = cell1

and cell2 would have been reallocated to the same shape as cell1
and the the components of each element of the cell2 array would
have been allocated if necessary.

WARNING: you said earlier that you were ifort 10.1. This compiler
does not behave in a standard way when assignments to whole
allocatable arrays are carried out, unless you use some switch
at compile time. Check the ifort documentation carefully for
the exact nature of its behavior. It's not standard without
the switch.

--
write(*,*) transfer((/17.392111325966148d0,6.5794487871554595D-85, &
6.0134700243160014d-154/),(/'x'/)); end