|
forums.silverfrost.com Welcome to the Silverfrost forums
|
View previous topic :: View next topic |
Author |
Message |
DanRRight
Joined: 10 Mar 2008 Posts: 2826 Location: South Pole, Antarctica
|
Posted: Sat May 25, 2019 9:49 pm Post subject: Allocation of derived type not standard conforming |
|
|
What danger this can have due to this warning
Code: | "0003) real*4, allocatable, dimension(:,:,: ) :: arr
WARNING - The use of ALLOCATABLE in the definition of a derived TYPE is not
standard conforming. No auto deallocation.". | Why is this not standard conforming ? How make it standard conforming ?
Code: |
module mod1
type ArrType01
real*4, allocatable, dimension(:,:,:) :: aaa
end type ArrType01
type (ArrType01) izk(3)
end module mod1
!......................................
Program Prog1
use mod1
allocate ( izk(1)%aaa(11,11,11) )
allocate ( izk(2)%aaa(22,22,22) )
allocate ( izk(3)%aaa(33,33,33) )
end Prog1 |
Last edited by DanRRight on Tue May 28, 2019 5:47 am; edited 1 time in total |
|
Back to top |
|
|
mecej4
Joined: 31 Oct 2006 Posts: 1888
|
Posted: Sun May 26, 2019 1:06 am Post subject: |
|
|
Allocatable components of derived types were not allowed in Fortran 95, but were added later in TR15581, and are allowed in F2003 and later versions. |
|
Back to top |
|
|
DanRRight
Joined: 10 Mar 2008 Posts: 2826 Location: South Pole, Antarctica
|
Posted: Sun May 26, 2019 11:07 am Post subject: |
|
|
Mecej4, thanks. I know that the allocation of derived types works with FTN95 for sure almost a decade. Now question probably more to Silverfrost: Is this now standard conforming in FTN95 or still not? What specifically this warning reminds us respect to deallocation? |
|
Back to top |
|
|
mecej4
Joined: 31 Oct 2006 Posts: 1888
|
|
Back to top |
|
|
PaulLaidler Site Admin
Joined: 21 Feb 2005 Posts: 7930 Location: Salford, UK
|
Posted: Mon May 27, 2019 9:30 am Post subject: |
|
|
This issue dates back to http://forums.silverfrost.com/viewtopic.php?t=1006.
The warning is no longer correct (or perhaps needs refining).
When using ALLOCATABLE components of a derived TYPE, FTN95 responds in various ways depending on the use of /ISO and /F2K.
/F2K is now the default.
The underlying question is, does FTN95 automatically deallocate these allocated components when the root object goes out of scope and what does the Standard say about this?
My initial guess is a) FTN95 does not do the automatic deallocation and this could be quite tricky to implement and b) it won't be a simple matter to work out what the Standard has to say about this (if anything).
So I guess a warning of some kind is still in order.
I have made a note that this needs further investigation. |
|
Back to top |
|
|
DanRRight
Joined: 10 Mar 2008 Posts: 2826 Location: South Pole, Antarctica
|
Posted: Mon May 27, 2019 10:44 pm Post subject: |
|
|
Thanks Mecej4 and Paul |
|
Back to top |
|
|
JohnCampbell
Joined: 16 Feb 2006 Posts: 2556 Location: Sydney
|
Posted: Tue May 28, 2019 5:29 am Post subject: |
|
|
Paul identifies that ALLOCATABLE components of a derived TYPE could be handled better in the Fortran Standard.
Their use also comes with some issues that need to be considered.
1) apparently they may not be automatically DEALLOCATEd if the derived type is an allocatable array structure. (is this definitely a memory leak ?)
2) the memory overhead for defining an ALLOCATABLE component is significant. It can be 48 bytes, (varies with array dimension) which makes these not suitable for small array components. So unless there is a significant variation in the dimension/size of each ALLOCATABLE component or sparseness of allocation, then a fixed size array component may be better.
3) their "size" is not included when trying to find the size of the derived type, especially when using the extension SIZEOF (not (yet?) available in FTN95 but is in other compilers)
I don't know why the deallocate and size reporting problems are not fixed in the compilers. Must be a reluctance to be standard non-conforming.
I have used them effectively for an in-memory database of element arrays in my 64-bit FE analysis, which has some sparsity and component array sizes vary from 50 to 8000 bytes.
I would not use ALLOCATABLE if component array sizes varied from 0 - 100 bytes.
ALLOCATABLE components may look good but there are some practical limitations to their use. |
|
Back to top |
|
|
DanRRight
Joined: 10 Mar 2008 Posts: 2826 Location: South Pole, Antarctica
|
Posted: Tue May 28, 2019 5:45 am Post subject: |
|
|
John,
What do you mean by "the memory overhead for defining an ALLOCATABLE component is significant. It can be 48 bytes". Do you mean that if we allocate 100x100 real*4 matrix the allocated space will be not 32*100*100 but 48*100*100 bits ? Or it will be 32*100*100 + 48 ?
Respect to deallocation, i plan to do that manually, but curious when in other more simple cases deallocation happens automatically? Does it takes place when you allocated array locally in the subroutine and then exit subroutine?
Last edited by DanRRight on Tue May 28, 2019 9:32 pm; edited 1 time in total |
|
Back to top |
|
|
JohnCampbell
Joined: 16 Feb 2006 Posts: 2556 Location: Sydney
|
Posted: Tue May 28, 2019 6:22 am Post subject: |
|
|
Dan,
I have a derived type which is a large array, with each element of the array having a number of allocatable components. My comment refers to the overhead of defining the size of each allocatble component.
If your allocatable component is array(:,:) and is allocated as:
ALLOCATE ( der_typ(I)%array(100,100), stat=stat )
In this case array would take up 100*100*4 bytes + possibly 72 bytes in the der_typ definition for it's size. "array(100,100)" is not a small array.
If you had:
ALLOCATE ( der_typ(I)%array(2,2), stat=stat ), this would take 16 bytes for the array + 72 bytes for the size definition, so the size overhead is a problem.
My example shows that if ns and nd are small (1:3) there is a significant overhead for defining the structure, but if ns,nd = 100 the overhead is relatively insignificant. It depends on how big "max_elements" is.
For small ns,nd it is probably better to have arrays dimensioned for max(ns) and max(nd), and not use allocatable components. A linked tree of triples could be an example of where allocatable size is not efficient.
Code: | module ELEM_DATA_BASE
integer*4 :: max_elements ! n0elem
!
TYPE elem_array_record ! set in elcomp
integer :: nd
integer :: ns
integer*4, allocatable :: lm(:) ! (nd) element equation map
real*8, allocatable :: st(:,:) ! (ns,nd) element stress matrix
END TYPE elem_array_record
!
type (elem_array_record), allocatable :: elem_array_records(:) ! (max_elem_records)
!
end module ELEM_DATA_BASE
!
use ELEM_DATA_BASE
!
integer iel, ns, nd
!
max_elements = 200000
allocate ( elem_array_records(max_elements) )
do iel = 1,max_elements
nd = mod(iel,3)
ns = 2
elem_array_records(iel)%nd = nd
elem_array_records(iel)%ns = ns
if ( nd == 0 ) cycle
allocate ( elem_array_records(iel)%lm(nd) )
allocate ( elem_array_records(iel)%st(ns,nd) )
end do
!
end
|
|
|
Back to top |
|
|
PaulLaidler Site Admin
Joined: 21 Feb 2005 Posts: 7930 Location: Salford, UK
|
Posted: Tue May 28, 2019 3:28 pm Post subject: |
|
|
I can confirm that FTN95 does not automatically deallocate ALLOCATABLE components of a derived TYPE (when the subprogram in which they are allocated RETURNs).
I will up date the associated compiler warning. |
|
Back to top |
|
|
John-Silver
Joined: 30 Jul 2013 Posts: 1520 Location: Aerospace Valley
|
Posted: Tue May 28, 2019 10:18 pm Post subject: |
|
|
So it simply means that one should explicitly DEALLOCATE before finishing ?
Which is not a bad practice anyway is it !
A subject which is sort of analagous to the pros and cons in the long running 'IMPLICIT NONE' debate.
If you don't DEALLOCATE explicitly you can never be sure what the compiler IS doing only what it SHOULD be doing.
As that great progrrammer/comedian Bill Rattleyerlance once said ..... to D(allocate) or not D(allocate), that is the memory leak risk ... well summat like that. _________________ ''Computers (HAL and MARVIN excepted) are incredibly rigid. They question nothing. Especially input data.Human beings are incredibly trusting of computers and don't check input data. Together cocking up even the simplest calculation ... " |
|
Back to top |
|
|
wahorger
Joined: 13 Oct 2014 Posts: 1217 Location: Morrison, CO, USA
|
Posted: Wed May 29, 2019 8:03 pm Post subject: |
|
|
I have an issue with the handling of allocatables in derived types as well.
The following test code should say that the variable is not allocated in the first test, and is allocated in the second test. In the first test, the ALLOCATED() function returns true, and should not.
Code: |
type:: abcd
sequence
integer,allocatable:: vector(:)
end type
type (abcd):: my_def
if(allocated(my_def%vector)) then
print *,'This is in error'
else
print *,'This is correct'
endif
allocate(my_def%vector(10))
if(.not.allocated(my_def%vector)) then
print *,'This is in error'
else
print *,'This is correct'
endif
end
|
Also the warning is that my_def is not allocatable and therefore cannot be in an ALLOCATED() call, but I am checking the vector component.
I was using the ALLOCATED function to see if the memory for VECTOR was already allocated. Since ALLOCATED() said it was allocated, the allocation was not performed, and the program crashes (as expected). |
|
Back to top |
|
|
JohnCampbell
Joined: 16 Feb 2006 Posts: 2556 Location: Sydney
|
Posted: Thu May 30, 2019 2:14 am Post subject: |
|
|
Bill,
Thanks for the example. I have expanded and this appears to be an error.
If after testing the status of vector, if I deallocate, the program crashes.
Alternatively, if I allocate, test is correct and then deallocate test is now correct.
Code: | type abcd
! sequence
integer :: n
integer,allocatable :: vector(:)
end type
type (abcd), allocatable :: my_def(:)
integer :: n, stat
write (*,*) 'allocated my_def =',allocated(my_def)
allocate ( my_def(5), stat=stat )
write (*,*) 'allocate my_def(5), stat=',stat
write (*,*) 'allocated my_def =',allocated(my_def)
if ( allocated(my_def(1)%vector) ) then
print *,'This is in error'
!z this code crashes program
!z deallocate ( my_def(1)%vector, stat=stat )
!z write (*,*) 'deallocate my_def(1)%vector, stat=',stat
!z write (*,*) 'allocated(my_def(1)%vector =', allocated(my_def(1)%vector)
else
print *,'This is correct'
end if
write (*,*) 'allocated(my_def(1)%vector =', allocated(my_def(1)%vector)
allocate ( my_def(1)%vector(10), stat=stat )
write (*,*) 'allocate my_def(1)%vector(10), stat=',stat
write (*,*) 'allocated(my_def(1)%vector =', allocated(my_def(1)%vector)
if( .not. allocated(my_def(1)%vector)) then
print *,'This is in error'
else
print *,'This is correct'
endif
deallocate ( my_def(1)%vector, stat=stat )
write (*,*) 'deallocate my_def(1)%vector, stat=',stat
write (*,*) 'allocated(my_def(1)%vector =', allocated(my_def(1)%vector)
allocate ( my_def(1)%vector(10), stat=stat )
write (*,*) 'allocate my_def(1)%vector(10), stat=',stat
write (*,*) 'allocated(my_def(1)%vector =', allocated(my_def(1)%vector)
end |
In my actual code, I use allocatable components in a module type array but rarely deallocate these components. |
|
Back to top |
|
|
wahorger
Joined: 13 Oct 2014 Posts: 1217 Location: Morrison, CO, USA
|
Posted: Thu May 30, 2019 4:30 am Post subject: |
|
|
There may be a problem with the allocate(absolute_address= . I cannot duplicate it with a simple example. Specifically, the ALLOCATE appears to initialize the memory at the absolute address. It happens in my callback:
Code: |
integer function choose_state_new_callback()
use mswin
include 'parametersandtypes.ins'
include 'quad_special.ins'
include 'control_types.ins'
integer,external:: log_mydata
type (qstsc_input_struct),pointer:: struct
integer:: user_data
user_data = clearwin_info@('USER_DATA')
write(log_mydata(9),*)'Memory at callback choose_state_new_callback'
call dump_memory(user_data,128)
allocate(struct,absolute_address=user_data)
call dump_memory(loc(struct),128)
! code
! mov eax%,user_data
! mov struct,eax%
! edoc
choose_state_new_callback = 1
select case (clearwin_string@('CALLBACK_REASON'))
CASE ('ITEM_SELECTED')
Line 470: if(struct%state_selection%list_item_selected.eq.0)return
|
With this error:
Quote: |
Runtime error from program:f:\cmasterf95\checkmate\win32\c-master.exe
Run-time Error
Error: Reference through unset Fortran POINTER
CHOOSE_STATE_NEW_CALLBACK - in file scfunc01.for at line 490 [+0284]
GETFIL - in file getfil.for at line 64 [+068f]
XMCLOG - in file clog.for at line 169 [+1225]
NEWMAIN - in file cmain.for at line 883 [+1d93]
main - in file cmain.for at line 162 [+227c]
|
The DUMP_MEMORY (before the ALLOCATE and after) reads:
Quote: |
Memory at callback choose_state_new_callback
Location=38C85370 Length= 128
38C85370 64 E0 21 35 5E 2C 1C 39 6C 5D C8 38 66 2C 1C 39
38C85380 00 00 00 00 88 13 00 00 01 00 00 00 01 00 00 00
38C85390 87 13 00 00 80 80 80 80 80 80 80 80 80 80 80 80
38C853A0 80 80 80 80 80 80 80 80 80 80 80 80 80 80 80 80
38C853B0 80 DF 21 35 80 80 80 80 80 80 80 80 80 80 80 80
38C853C0 80 80 80 80 80 80 80 80 80 80 80 80 80 80 80 80
38C853D0 5A 2C 1C 39 6C 5D C8 38 B8 2B 1C 39 00 00 00 00
38C853E0 4B 00 00 00 01 00 00 00 01 00 00 00 4A 00 00 00
Location=38C85370 Length= 128
38C85370 80 80 80 80 80 80 80 80 80 80 80 80 80 80 80 80
38C85380 80 80 80 80 80 80 80 80 80 80 80 80 80 80 80 80
38C85390 80 80 80 80 80 80 80 80 80 80 80 80 80 80 80 80
38C853A0 80 80 80 80 80 80 80 80 80 80 80 80 80 80 80 80
38C853B0 80 80 80 80 80 80 80 80 80 80 80 80 80 80 80 80
38C853C0 80 80 80 80 80 80 80 80 80 80 80 80 80 80 80 80
38C853D0 80 80 80 80 80 80 80 80 80 80 80 80 80 80 80 80
38C853E0 80 80 80 80 80 80 80 80 80 80 80 80 80 80 80 80
|
I could not determine the number of bytes in the TYPE being displayed, but the fact that the data is initialized to the UNDEFINED pattern is some evidence of an issue, I think. If I comment out the ALLOCATE and uncomment the CODE/EDOC sequence, it all works. |
|
Back to top |
|
|
PaulLaidler Site Admin
Joined: 21 Feb 2005 Posts: 7930 Location: Salford, UK
|
Posted: Thu May 30, 2019 6:51 am Post subject: |
|
|
I have made a note that these bugs need fixing.
Curiously, the 64 bit version of Bill's code runs correctly for me. |
|
Back to top |
|
|
|
|
You cannot post new topics in this forum You cannot reply to topics in this forum You cannot edit your posts in this forum You cannot delete your posts in this forum You cannot vote in polls in this forum
|
Powered by phpBB © 2001, 2005 phpBB Group
|