forums.silverfrost.com Forum Index forums.silverfrost.com
Welcome to the Silverfrost forums
 
 FAQFAQ   SearchSearch   MemberlistMemberlist   UsergroupsUsergroups   RegisterRegister 
 ProfileProfile   Log in to check your private messagesLog in to check your private messages   Log inLog in 

Allocation of derived type not standard conforming
Goto page 1, 2  Next
 
Post new topic   Reply to topic    forums.silverfrost.com Forum Index -> General
View previous topic :: View next topic  
Author Message
DanRRight



Joined: 10 Mar 2008
Posts: 2813
Location: South Pole, Antarctica

PostPosted: Sat May 25, 2019 9:49 pm    Post subject: Allocation of derived type not standard conforming Reply with quote

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
View user's profile Send private message
mecej4



Joined: 31 Oct 2006
Posts: 1884

PostPosted: Sun May 26, 2019 1:06 am    Post subject: Reply with quote

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
View user's profile Send private message
DanRRight



Joined: 10 Mar 2008
Posts: 2813
Location: South Pole, Antarctica

PostPosted: Sun May 26, 2019 11:07 am    Post subject: Reply with quote

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
View user's profile Send private message
mecej4



Joined: 31 Oct 2006
Posts: 1884

PostPosted: Mon May 27, 2019 8:35 am    Post subject: Reply with quote

Allocation of variables of derived types is a separate topic from derived types with allocatable components. Your example had a derived type with one or more allocatable components. It did not declare any allocatable variables of that derived type.

See also https://software.intel.com/en-us/forums/intel-visual-fortran-compiler-for-windows/topic/295172 .
Back to top
View user's profile Send private message
PaulLaidler
Site Admin


Joined: 21 Feb 2005
Posts: 7914
Location: Salford, UK

PostPosted: Mon May 27, 2019 9:30 am    Post subject: Reply with quote

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
View user's profile Send private message AIM Address
DanRRight



Joined: 10 Mar 2008
Posts: 2813
Location: South Pole, Antarctica

PostPosted: Mon May 27, 2019 10:44 pm    Post subject: Reply with quote

Thanks Mecej4 and Paul
Back to top
View user's profile Send private message
JohnCampbell



Joined: 16 Feb 2006
Posts: 2551
Location: Sydney

PostPosted: Tue May 28, 2019 5:29 am    Post subject: Reply with quote

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
View user's profile Send private message
DanRRight



Joined: 10 Mar 2008
Posts: 2813
Location: South Pole, Antarctica

PostPosted: Tue May 28, 2019 5:45 am    Post subject: Reply with quote

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
View user's profile Send private message
JohnCampbell



Joined: 16 Feb 2006
Posts: 2551
Location: Sydney

PostPosted: Tue May 28, 2019 6:22 am    Post subject: Reply with quote

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
View user's profile Send private message
PaulLaidler
Site Admin


Joined: 21 Feb 2005
Posts: 7914
Location: Salford, UK

PostPosted: Tue May 28, 2019 3:28 pm    Post subject: Reply with quote

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
View user's profile Send private message AIM Address
John-Silver



Joined: 30 Jul 2013
Posts: 1520
Location: Aerospace Valley

PostPosted: Tue May 28, 2019 10:18 pm    Post subject: Reply with quote

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 ... Smile "
Back to top
View user's profile Send private message
wahorger



Joined: 13 Oct 2014
Posts: 1214
Location: Morrison, CO, USA

PostPosted: Wed May 29, 2019 8:03 pm    Post subject: Reply with quote

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
View user's profile Send private message Visit poster's website
JohnCampbell



Joined: 16 Feb 2006
Posts: 2551
Location: Sydney

PostPosted: Thu May 30, 2019 2:14 am    Post subject: Reply with quote

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
View user's profile Send private message
wahorger



Joined: 13 Oct 2014
Posts: 1214
Location: Morrison, CO, USA

PostPosted: Thu May 30, 2019 4:30 am    Post subject: Reply with quote

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
View user's profile Send private message Visit poster's website
PaulLaidler
Site Admin


Joined: 21 Feb 2005
Posts: 7914
Location: Salford, UK

PostPosted: Thu May 30, 2019 6:51 am    Post subject: Reply with quote

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
View user's profile Send private message AIM Address
Display posts from previous:   
Post new topic   Reply to topic    forums.silverfrost.com Forum Index -> General All times are GMT + 1 Hour
Goto page 1, 2  Next
Page 1 of 2

 
Jump to:  
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