Array of Fortran derived types and memory leaks despite completion

I defined a derived type and ran into some problems with freeing up memory, although I wrote the final procedure. The code is as follows

module ModuleCoordinate implicit none type :: TCoordinate real(8),dimension(:),pointer :: Coordinate => NULL() contains procedure :: TCoordinateAssignment generic,public :: Assignment(=) => TCoordinateAssignment final :: TCoordinateDel end type TCoordinate interface TCoordinate module procedure :: TCoordinateInit end interface TCoordinate contains subroutine TCoordinateDel(self) type(TCoordinate),intent(inout) :: self if(associated(self%Coordinate))deallocate(self%Coordinate) end subroutine TCoordinateDel subroutine TCoordinateAssignment(O1,O2) class(TCoordinate),intent(out) :: O1 type(TCoordinate),intent(in) :: O2 if(associated(O2%Coordinate))allocate(O1%Coordinate,source=O2%Coordinate) end subroutine TCoordinateAssignment type(TCoordinate) function TCoordinateInit(IVal1,IVal2) result(self) real(8),intent(in) :: IVal1,IVal2 allocate(self%Coordinate(2)) self%Coordinate=(/IVal1,IVal2/) end function TCoordinateInit end module ModuleCoordinate 

The verification code is as follows

 program test implicit none integer(4),parameter :: NLoop=40000 integer(4) :: i do i=1,NLoop call TestMemory1() call TestMemory2() end do pause end program test subroutine TestMemory1() use ModuleCoordinate implicit none integer(4),parameter :: DN=10 integer(4) :: i type(TCoordinate),dimension(DN) :: a do i=1,DN a(i)=TCoordinate(1.0_8,1.0_8) end do end subroutine TestMemory1 subroutine TestMemory2() use ModuleCoordinate implicit none type(TCoordinate) :: b1,b2,b3,b4,b5,b6,b7,b8,b9,b10 b1=TCoordinate(1.0_8,1.0_8) b2=TCoordinate(1.0_8,1.0_8) b3=TCoordinate(1.0_8,1.0_8) b4=TCoordinate(1.0_8,1.0_8) b5=TCoordinate(1.0_8,1.0_8) b6=TCoordinate(1.0_8,1.0_8) b7=TCoordinate(1.0_8,1.0_8) b8=TCoordinate(1.0_8,1.0_8) b9=TCoordinate(1.0_8,1.0_8) b10=TCoordinate(1.0_8,1.0_8) end subroutine TestMemory2 

It turns out that the TestMemory2 routine TestMemory2 OK, but TestMemory1 is not, which means that when an array of this derived type is declared, the final procedure does not work and there is a memory leak.

However, if I remove => NULL() right of the Coordinate in the definition of this derived type, both routines seem to work well.

What is the difference when the coordinate Coordinate freed? If this is important, then complier is ifort_2013_sp1.3.174.

+2
source share
1 answer

In the description of the finalization process we see (Fortran 2008, 4.5.6.2)

If the dynamic type of an object has a final routine whose dummy argument has the same type parameters and is ranked as an object to be terminated, it is called with the entity as the actual argument. Otherwise, if there is an elementary final routine whose dummy argument has the same type as the object that is being completed, it is called with the entity as the actual argument. Otherwise, the subroutine will not be called at this point.

There is a final subroutine for a derived type, provided only for scalar (rank-0) objects. To complete the finalization for your rank-1 object, the easiest way (it seems, in this case) is to make your subroutine elementary.

I'm a little reluctant to mention the aspect =>NULL() , since I don't have current testing tools for what I'm going to write, but I will reflect.

Without =>NULL() initialization, by default, the pointer component has an undefined association status. That means when you do

  b1=TCoordinate(1.0_8,1.0_8) 

interesting things happen.

As part of the assignment, b1 ends when you TCoordinateAssignment . Completion involves calling associated with a pointer that has an undefined association status. This is not allowed (as a result of which any result may occur).

+1
source

Source: https://habr.com/ru/post/983765/


All Articles