来自derrived类型的程序中的动态内存释放

问题描述 投票:1回答:1

我是Fortran的新手,所以我想对动态内存的分配有一些了解

我读到了关于动态内存分配的内容,各种来源对此主题有不同的看法。例如,一本书指出必须在程序结束时释放每个分配的动态内存块,以避免内存泄漏。但是,其他来源(书籍和各种网页)声称无效,因为编译器(gfortran等)会在程序结束时自动释放所有动态对象,数组等。

所以在我的示例代码中,我不知道是否需要从NN_VOD过程中释放动态数组CALCULATE_DATA_DM

如果我想避免内存泄漏并且此代码中是否存在任何内存泄漏,我需要对此示例代码执行什么操作? (我的IDE是Code :: Blocks 17.12 with MinGW compiler 6.3.0)

MODULE DERRIVED_TYPE_TMP

  INTEGER, PUBLIC :: I, J, K, ALLOC_ERR

  TYPE, PUBLIC :: DM_ELEMENT
     CHARACTER( 50 ), PRIVATE :: ELE_NAME
     INTEGER,         PRIVATE :: ELE_NUMBER
   CONTAINS
     PROCEDURE, PUBLIC :: CALCULATE_ELEMENT => CALCULATE_DATA_ELEMENT
  END TYPE DM_ELEMENT

  PRIVATE :: CALCULATE_DATA_ELEMENT

  TYPE, EXTENDS(DM_ELEMENT), PUBLIC :: VOD_DM
     INTEGER, ALLOCATABLE, PRIVATE :: NN_VOD( : )
   CONTAINS

     PROCEDURE, PUBLIC :: CALCULATE_ELEMENT => CALCULATE_DATA_DM
     PROCEDURE, PUBLIC ::           TAKE_DM =>      TAKE_DATA_DM
  END TYPE VOD_DM

  PRIVATE :: CALCULATE_DATA_DM
  PRIVATE :: TAKE_DATA_DM

CONTAINS

  SUBROUTINE CALCULATE_DATA_ELEMENT ( THIS, NUMBER_TMP )
    CLASS( DM_ELEMENT )   :: THIS
    INTEGER, INTENT( IN ) :: NUMBER_TMP
  END SUBROUTINE CALCULATE_DATA_ELEMENT

  SUBROUTINE CALCULATE_DATA_DM( THIS, NUMBER_TMP )
    CLASS( VOD_DM )       :: THIS
    INTEGER, INTENT( IN ) :: NUMBER_TMP

    IF ( .NOT. ALLOCATED( THIS%NN_VOD ) ) ALLOCATE( THIS%NN_VOD( NUMBER_TMP ), STAT = ALLOC_ERR )
    IF ( ALLOC_ERR .NE. 0 )                STOP ( "PROBLEM SA ALOKACIJOM MEMORIJE - THIS%T !!!" )
    DO J = 1, NUMBER_TMP
       THIS%NN_VOD( J ) = J + NUMBER_TMP
    END DO
  END SUBROUTINE CALCULATE_DATA_DM

  FUNCTION TAKE_DATA_DM( THIS, INDX ) RESULT( RESULT_TMP )
    CLASS( VOD_DM )        :: THIS
    INTEGER, INTENT( IN ) :: INDX
    INTEGER               :: RESULT_TMP

    RESULT_TMP = THIS%NN_VOD( INDX )
  END FUNCTION TAKE_DATA_DM

END MODULE DERRIVED_TYPE_TMP

PROGRAM DO_LOOP_ALLOCATION
  USE, NON_INTRINSIC :: DERRIVED_TYPE_TMP
  IMPLICIT NONE

  INTEGER,   PARAMETER :: N_NN_DM = 3
  INTEGER,   PARAMETER :: AN_NN_DM( N_NN_DM ) = [ 2, 3, 4 ]

  TYPE :: NN_VOD
     TYPE( VOD_DM ), ALLOCATABLE :: ID( : )
  END TYPE NN_VOD

  CLASS( DM_ELEMENT ),             POINTER :: P_DM_ELEMENT
  TYPE     ( NN_VOD ), ALLOCATABLE, TARGET ::   PAR_NN_VOD( : )

  IF ( .NOT. ALLOCATED( PAR_NN_VOD ) ) ALLOCATE( PAR_NN_VOD( N_NN_DM ), STAT = ALLOC_ERR )
  IF ( ALLOC_ERR .NE. 0 )              STOP ( "ALLOCATION ERROR - PAR_NN_VOD !!!" )

  DO K = 1, N_NN_DM
     IF ( .NOT. ALLOCATED( PAR_NN_VOD( K )%ID ) ) ALLOCATE( PAR_NN_VOD( K )%ID( AN_NN_DM( K ) ), STAT = ALLOC_ERR )
     IF ( ALLOC_ERR .NE. 0 )                      STOP ( "ALLOCATION ERROR - PAR_NN_VOD%ID !!!")
  END DO

  DO K = 1, N_NN_DM
     DO I = 1, AN_NN_DM( K )
        P_DM_ELEMENT => PAR_NN_VOD( K )%ID( I )
        CALL P_DM_ELEMENT%CALCULATE_ELEMENT( K + I )
     END DO
  END DO

END PROGRAM DO_LOOP_ALLOCATION
fortran gfortran
1个回答
1
投票

从Fortran95开始,语言的设计使得使用标准的符合编译器时,使用可分配数组时不可能有内存泄漏,因为一旦可分配对象超出范围,它就会被解除分配。这是可分配数组的一大优势,也是可能始终优先使用指针的原因之一。现在,当变量停止使用后,变量超出范围可能很长,因此您可能希望先前手动解除分配以节省内存,但是不需要纯粹解除分配以避免内存泄漏。因此在您的代码中使用可分配的数组,并且不会有内存泄漏。

在Fortran 90中,这不是真的,可以使用可分配的内存泄漏。但是这个标准早已被Fortran 95和它取代,因此今天不应该使用Fortran 90和所有早期标准。

© www.soinside.com 2019 - 2024. All rights reserved.