Динамическое освобождение памяти в процедуре от приводного типа - PullRequest
0 голосов
/ 13 февраля 2019

Я новичок в Fortran, поэтому я хотел бы получить некоторое представление о распределении динамической памяти

Я читал о динамическом распределении памяти, и различные источники по-разному относятся к этой теме.Например, одна книга утверждает, что каждый отдельный блок выделенной динамической памяти должен быть освобожден в конце программы, чтобы избежать утечек памяти .Однако другие источники (книги и различные веб-страницы) утверждают, что это недопустимо, поскольку компиляторы (gfortran и аналогичные) автоматически освобождают все динамические объекты, массивы и т. Д. В конце программы.

Так что в моем примере кода я не знаю, нужно ли освобождать динамический массив NN_VOD из CALCULATE_DATA_DM процедуры.

Что мне нужно делать с этим примером кода, если я хочу избежать памятиутечка и есть ли утечка памяти в этом коде?(Моя IDE - это Code :: Blocks 17.12 с компилятором MinGW 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

1 Ответ

0 голосов
/ 13 февраля 2019

Начиная с Fortran95, язык спроектирован таким образом, что при использовании стандартного компилятора невозможно иметь утечку памяти при использовании выделяемых массивов, так как после того, как выделяемый объект выходит из области видимости, он освобождается.Это одно из больших преимуществ выделяемых массивов и одна из причин, по которой их всегда следует использовать в предпочтении указателям, где это возможно.Теперь, когда переменная выходит из области видимости, может пройти много времени после того, как она перестает использоваться, и поэтому вы можете захотеть отменить ее раньше, чтобы сэкономить память, но нет необходимости просто освобождать ее, чтобы избежать утечки памяти.Таким образом, в вашем коде используйте размещаемые массивы, и утечки памяти не будет.

В Fortran 90 это было не так, утечки памяти с помощью выделяемых элементов были возможны.Но этот стандарт давно заменен Fortran 95 и таким образом, и поэтому Fortran 90 и все более ранние стандарты не должны использоваться сегодня.

...