Утечка памяти при использовании одного и того же указателя на многочисленные цели - PullRequest
0 голосов
/ 03 июня 2018

Моя IDE - это Visual Studio 2010 со встроенным компилятором Intel Fortran.Версия компилятора: Intel Parallel Studio XE 2011.

Я не опытный программист на Фортране, поэтому мне нужна небольшая помощь по использованию указателей при чтении данных из файлов .txt.Это мой пример кода:

Module Derived_type

implicit none

Type , public :: Something

  private

       Real :: Somth_1
    Integer :: Somth_2

  contains

    procedure , public :: read_input => read_data_input
    procedure , public :: t_Somth_1 => t_data_Somth_1
    procedure , public :: t_Somth_2 => t_data_Somth_2

End Type Something

private :: read_data_input
private :: t_data_Somth_1 , t_data_Somth_2

contains

Subroutine read_data_input( This , Un_r )

  Class( Something ) :: This
  Integer , intent( in ) :: Un_r

  Read ( Un_r , * , Err = 100 ) This%Somth_1
  Read ( Un_r , * , Err = 101 ) This%Somth_2

Return

100 Stop ( "Read format error - 100 !!!" )
101 Stop ( "Read format error - 101 !!!" )

End Subroutine read_data_input

Function t_data_Somth_1 ( This ) result( data_Somth_1 )

  Class( Something ) :: This
  Real :: data_Somth_1

  data_Somth_1 = This%Somth_1

End Function t_data_Somth_1

Function t_data_Somth_2 ( This ) result( data_Somth_2 )

  Class( Something ) :: This
  Integer :: data_Somth_2

  data_Somth_2 = This%Somth_2

End Function t_data_Somth_2

End Module Derived_type

Program Memory_leaking

Use , non_intrinsic :: Derived_type

Implicit none

Integer :: i , alloc_err , dealloc_err
Integer , parameter :: N_snv = 3
Character( 256 ) :: Name
Character(*),parameter :: a00 = '("Input_",i1,".txt")'

Class( Something ) , pointer :: Po_Something

Type( Something ) , allocatable , target :: Tar_Something(:)

! Memory allocation

allocate ( Po_Something , Stat = alloc_err )

If ( alloc_err .ne. 0 ) Stop ( "Allocation wrong - Po_Something !!!")

If ( .not. allocated ( Tar_Something ) ) allocate( Tar_Something( N_snv ) , stat = alloc_err )

If ( alloc_err .ne. 0 ) Stop ( "Allocation wrong - Tar_Something !!!")


Do i = 1 , N_snv

   Po_Something => Tar_Something(i)

   Write( Name , a00 ) i

   Open( 15 , File = Name , Status = 'Unknown' , Action = 'Read' )

      Call Po_Something%read_input( 15 )

   Close( 15 , Status = 'Keep' )

   Write(*,*) Po_Something%t_Somth_1() , Po_Something%t_Somth_2()

End Do

! Memory deallocation

deallocate ( Po_Something , Stat = dealloc_err )

If ( dealloc_err .ne. 0 ) Stop ( "deAllocation wrong - Po_Something !!!")

If ( allocated ( Tar_Something ) ) deallocate( Tar_Something, stat = dealloc_err )

If ( dealloc_err .ne. 0 ) Stop ( "deAllocation wrong - Tar_Something !!!")

End program Memory_leaking

У меня есть один массив, который является производным типом, и я хочу читать данные из файла .txt для каждого отдельного массива, используя тот же указатель, как в моем примере кода.Мне нужно сломать соединение указателя и цели битвена, после чего выполнение цикла было выполнено?Есть ли утечка памяти в этом случае?

1 Ответ

0 голосов
/ 03 июня 2018

Да, у вас утечка памяти.

allocate ( Po_Something , Stat = alloc_err )

Здесь вы вручную распределили хранилище для переменной указателя и указали на ее адрес памяти.

Po_Something => Tar_Something(i)

Сразу после,вы изменили poitee на другое хранилище (выделяемая переменная) и оставили позади хранилище, выделенное ранее.После этой ассоциации указателей больше не остается ссылки, указывающей на адрес, выделенный вами вручную.Программа не сможет освободить его, когда он достигнет конца.

Поскольку вы не используете хранилище первого выделения, решение здесь просто не делает этого.Указатель будет указывать на память, уже выделенную в цикле.

Распределяемые переменные освобождаются автоматически (в современном Fortran), но любая память, выделенная вручную для переменной указателя, должна быть вручную удалена перед изменением ее цели.

Проверьте мой другой ответ о том, когда ручное освобождение необходимо для справки. Когда требуется освобождение массива?

(лучше скачать копию стандарта Fortran для справки здесь https://wg5 -fortran.org )

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...