Как правильно доработать объект на Фортране?

У меня есть объект, анализирующий текстовый файл. Вот моя основная программа:

program main
use Parser_class 
implicit none
type(Parser) :: Parser
call Parser%ProcessFile('data.txt')
call Parser%Deallocate
end program main

где определение типа

module Parser_class
type :: Parser
contains
    procedure, public :: ProcessFile
    procedure, public :: Deallocate
end type Parser
contains
    subroutine ProcessFile(self)
    ...
    end subroutine 
    subroutine Deallocate(self)
    class(Parser) :: self
    ...
    end subroutine 
end module Parser_class

Я прочитал о ключевом слове final и изменил определение типа на

module Parser_class
type :: Parser
contains
    procedure, public :: ProcessFile
    final :: Deallocate
end type Parser
contains
    subroutine ProcessFile(self)
    ...
    end subroutine 
    subroutine Deallocate(self)
    type(Parser) :: self
    ...
    end subroutine 
end module Parser_class

Кроме того, в основной программе у меня больше нет call Parser%Deallocate. Финализатор не вызывается сейчас в любое время. Я каким-то образом понимаю это, потому что я никогда не уничтожаю и не перезаписываю объект Parser. Но как я могу это сделать или как правильно справиться с процессом освобождения?


person THo    schedule 18.11.2016    source источник
comment
Я добавил end program. Программа работает по назначению (просто читает текстовые файлы). Я просто хочу знать, является ли мой способ использования call Parser%Deallocate правильным способом освобождения всех массивов или мне следует сделать это с финализаторами. Дополнительный вопрос заключается в том, когда именно вызываются финализаторы. Не могу предоставить рабочий пример, я новичок в OO Fortran.   -  person THo    schedule 18.11.2016


Ответы (1)


В стандарте Fortran 2008, когда происходит финализация, указано в разделе 4.5.6.31. Я не буду копировать все времена здесь, но я подытожу.

То, что ясно упоминается вслед за тем, когда, когда нет:

Если выполнение образа прерывается либо из-за ошибки (например, сбоя выделения), либо из-за выполнения команды stop-stmt, error-stop-stmt или end-program-stmt, объекты, существовавшие непосредственно перед завершением, не завершаются.

Это касается вашей программы. Parser находится в области действия программы и все еще существует в конце программы. Нет никаких очевидных других вещей, которые могли бы вызвать финализацию.

Если Deallocate является финальной процедурой для типа, то финализация объекта этого типа тонко отличается от вызова процедуры, связанной с типом. При финализации процесс является рекурсивным: компоненты и родители сами подлежат финализации. При вызове подпрограммы эта рекурсия должна каким-то образом появляться вручную.

Во многих случаях не важно, что сущность не завершена в конце программы. В конце концов, любое освобождение — это проблема операционной системы, а не программиста. Однако бывают случаи, когда другие формы уборки действительно желательны.

Настоящая финализация может быть форсирована некоторыми способами. Если изучить приведенный ниже список, на ум приходят два варианта:

  • сделать объект Parser доступным для размещения и явно освободить его;
  • оберните все это в конструкцию block.

Грубо говоря, когда происходит финализация:

  • когда есть освобождение (указатель или выделяемое);
  • как запуск процедуры с intent(out) аргументами;
  • при достижении конца исполняемой конструкции или подпрограммы для несохраненных локальных объектов;
  • непосредственно перед внутренним присвоением переменной;
  • после того, как значение результата функции закончено.

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

person francescalus    schedule 18.11.2016
comment
Спасибо за подробное объяснение. Я узнал, что я всегда должен освобождать все, что я выделяю, чтобы не создавать утечки памяти. Это устарело? Так что было бы нормально не вызывать подпрограммы освобождения памяти и просто позволить программе завершиться? - person THo; 18.11.2016
comment
Если это просто освобождение памяти, то утечки памяти не будут проблемой в конце программы. Они могут быть, когда указатели используются определенным образом, где финализация действительно помогла бы, но опять же даже с ними не в конце программа. Распределяемые объекты, как правило, безопасны. - person francescalus; 18.11.2016
comment
@THo Это устарело для языков, которые используют сборку мусора или подсчет ссылок. Распределяемые переменные Фортрана представляют собой очень простую форму подсчета ссылок, где count может быть только один. Вам не нужно явно освобождать выделяемые переменные, если вам не нужно освобождать память или снова выделять ее для чего-то другого. - person Vladimir F; 18.11.2016