Finalization when deallocating subcomponent of a derived type

Finalization when deallocating subcomponent of a derived type

hs-napa's picture

I found a memory leak with Intel Inspector XE 2011 when analyzing a fortran program compiled with compiler version:

Intel Visual Fortran Compiler XE for applications running on IA-32, Version 12.1.3.300 Build 20120130

After studying the problem I managed to produce a minimal example (at the end of the post).

I compiled the program with option /debug:full and analyzed it with Inspector. The result is that the memory allocated at line 23 (subroutine SET_ID) which is called from line 51 is not freed. Total of 2 bytes. There were no other memory leaks, which implies that the component OBJ of the TYPE(CONTAINER_T) is actually deallocated, but the finalization is not done.

If the explicit deallocation (commented line 56) is run the finalization occurs and Inspector is happy to report "no problems detected".

This behavior is a bit surprising. I tried to see what the FORTRAN 2003 standard says and found out that the CONTAINER_T itself is not finalizable. Quote from the standard (section 4.5.5, lines 21-22):

"A derived type is finalizable if it has any final subroutines or if it has any nonpointer, nonallocatable component whose type is finalizable."

However, even if the type itself is not finalizable I would expect that the automatic deallocation of the allocatable subcomponent would cause the same finalization procedure to occur as explicitly calling DEALLOCATE.

Regards,
-Heikki

MODULE FINALIZABLE
   IMPLICIT NONE
   TYPE :: FINALIZABLE_T

      PRIVATE

      CHARACTER(LEN=:), POINTER :: ID => NULL()

   CONTAINS

      PROCEDURE :: SET_ID

      FINAL :: FINALIZE

   END TYPE
   TYPE :: CONTAINER_T

      TYPE(FINALIZABLE_T), ALLOCATABLE :: OBJ(:)

   END TYPE
CONTAINS
   SUBROUTINE SET_ID( THIS, ID )

      CLASS(FINALIZABLE_T) :: THIS

      CHARACTER(LEN=*), INTENT(IN) :: ID

      IF ( ASSOCIATED( THIS % ID ) ) DEALLOCATE( THIS % ID )

      ALLOCATE( THIS % ID, SOURCE = ID )

   END SUBROUTINE
   ELEMENTAL SUBROUTINE FINALIZE( THIS )

      TYPE(FINALIZABLE_T), INTENT(INOUT) :: THIS

      IF ( ASSOCIATED( THIS % ID ) ) DEALLOCATE( THIS % ID )

   END SUBROUTINE
END MODULE
MODULE FINALIZATION_TEST
   USE FINALIZABLE
   IMPLICIT NONE
CONTAINS
   SUBROUTINE TEST

      TYPE(FINALIZABLE_T), ALLOCATABLE  :: A(:)

      TYPE(CONTAINER_T) :: B

      INTEGER :: I
      DO I = 1, SIZE(A)

         CALL A(I) % SET_ID( 'A' )

      END DO

      ALLOCATE( B % OBJ(2) )

      DO I = 1, SIZE(B % OBJ)

         CALL B % OBJ(I) % SET_ID( 'B' )

      END DO
      ! without explicit deallocation the finalization is not done

      ! memory leak is fixed by uncommenting following line

      !DEALLOCATE( B % OBJ )

   END SUBROUTINE
END MODULE
PROGRAM TEST_PROGRAM

   USE FINALIZATION_TEST

   IMPLICIT NONE

   CALL TEST

END PROGRAM

2 posts / 0 new
Last post
For more complete information about compiler optimizations, see our Optimization Notice.
hs-napa's picture

I studied the Fortran 2003 standard a bit more. It seems to me that in this case the finalization should occur even without the explicit deallocate. Please correct me, if I'm wrong.

The fortran standard states that: "When an allocatable entity is deallocated, it is finalized." (Section 4.5.5.2)

The finalization according to the standard should do the following: "... if there is an elemental final subroutine whose dummy argument has the same kind type parameters as the entity being finalized, it is called with the entity as an actual argument." (Section 4.5.5.1)

In this case there is an elemental final subroutine that matches the above condition. It seems that in this case the compiled code does not work according to the standard.

Regards,
-Heikki

Login to leave a comment.