Intel® Fortran Compiler
Build applications that can scale for the future with optimized code designed for Intel® Xeon® and compatible processors.
29274 Discussions

Finalization when deallocating subcomponent of a derived type

hs-napa
Beginner
396 Views
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

[fortran]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 [/fortran]

0 Kudos
1 Reply
hs-napa
Beginner
396 Views
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
0 Kudos
Reply