Silverfrost Forums

Welcome to our forums

Allocation of derived type not standard conforming

25 May 2019 8:49 (Edited: 28 May 2019 4:47) #23658

What danger this can have due to this warning

'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 ?

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 
26 May 2019 12:06 #23659

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.

26 May 2019 10:07 #23666

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?

27 May 2019 7:35 #23676

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 .

27 May 2019 8:30 #23677

This issue dates back to https://forums.silverfrost.com/Forum/Topic/760.

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.

27 May 2019 9:44 #23689

Thanks Mecej4 and Paul

28 May 2019 4:29 #23691

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.

28 May 2019 4:45 (Edited: 28 May 2019 8:32) #23692

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 real4 matrix the allocated space will be not 32100100 but 48100100 bits ? Or it will be 32100*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?

28 May 2019 5:22 #23693

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 1001004 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.

   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
28 May 2019 2:28 #23704

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.

29 May 2019 7:03 #23707

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.

	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).

30 May 2019 1:14 #23708

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.

    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.

30 May 2019 3:30 #23709

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:

	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:

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:

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:f70ca715c3] 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.

30 May 2019 5:51 #23711

I have made a note that these bugs need fixing.

Curiously, the 64 bit version of Bill's code runs correctly for me.

11 Jun 2019 2:47 #23763

A number of bugs have been revealed in this thread and hopefully they have all now been fixed for the next release of FTN95.

Specifically an array member of a derived type can now be ALLOCATABLE. However it is still the case that there is no corresponding automatic deallocation when a subprogram returns.

Please login to reply.