Окончательная процедура Fortran вызывает себя до того, как переменная выйдет за пределы области видимости

У меня проблема с деструкторами/конечными процедурами Fortran. Имея код ниже:

  module my_type_module
    implicit none

    type my_type
      contains
        final :: destructor
    end type my_type

    interface my_type
      ! Constructor declaration
      module procedure my_type_constructor
    end interface my_type

    contains
      function my_type_constructor()
        type(my_type) :: my_type_constructor

        print *, 'In constructor address is: ',
 &          loc(my_type_constructor)

      end function my_type_constructor

      subroutine destructor(this)
        type(my_type) :: this
        print *, 'Destructor of my_type object with address: ',
 &        loc(this)
      end subroutine destructor

  end module my_type_module

  program trial

    use my_type_module
    implicit none

    type(my_type) :: argument

    print *, 'Trial program starts'
    print *, 'Initial address is', loc(argument)

    argument = my_type_constructor()

    print *, 'Address afer constructor is called is', loc(argument)

    print *, 'doing some work...'
    print *, 'finishing program...'

    print *, 'Final address is', loc(argument)

  end program trial

вывод:

Trial program starts
Initial address is            4351590240
In constructor address is:        140734743834256
Destructor of my_type object with address: 4351590240
Destructor of my_type object with address: 140734743834256
Address afer constructor is called is      4351590240     
doing some work...
finishing program...
Final address is            4351590240

Получается, что сконструированный объект разрушается сразу же после окончания его построения, а не в конце программы. Есть идеи, что не так? Приведенный выше код был скомпилирован с помощью ifort 14.0.0,


person Puchatek    schedule 21.10.2013    source источник


Ответы (1)


Нет ничего плохого (за исключением очевидного (?) использования продолжения исходного кода фиксированной формы с кодом Fortran 2003 в 2013 году).

Первый вызов «деструктора» должен завершить левую часть оператора присваивания.

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

Объекты, существующие непосредственно перед завершением программы (в данном случае выполнением оператора завершения программы), не завершаются.

person IanH    schedule 21.10.2013
comment
Хорошо, я получаю, что конструктор возвращает объект по значению, следовательно, он также вызывает деструктор. Но поскольку деструктор для argument не вызывается в конце программы, как насчет высвобождения памяти для любых выделяемых членов (или производных членов), которые она может иметь? Компилятор позаботится об этом? - person Puchatek; 21.10.2013
comment
Ну ладно, я сделал небольшой пример и кажется, что да, так оно и есть. - person Puchatek; 21.10.2013
comment
Завершение и автоматическое освобождение — не одно и то же, хотя есть общие аспекты и требования к последовательности выполнения. В обоих случаях существует разница в поведении финализации и освобождения между концом программы и концом процедуры или концом конструкции BLOCK. - person IanH; 21.10.2013
comment
Кроме того, выделяемые ресурсы не нужно освобождать до завершения программы. Недавний патч AFAIK, который включил финализацию в gfortran, отключил автоматическое освобождение в конце программы, чтобы не вызывать финализацию. - person Vladimir F; 21.10.2013
comment
@IanH как насчет того, если вы, например. имеют указатели (например, связанный список) внутри объявленного типа my_type, компилятор не будет автоматически освобождать память, и поскольку процедура финализации не выполняется при завершении программы, какой смысл в финализации в этом случае? - person A2LBK; 29.12.2018