Finalisation in FORTRAN 2003

岁酱吖の 提交于 2021-01-27 11:55:51

问题


According to Fortran Wiki the intel fortran compiler version 14 should support finalisation defined in FORTRAN 2003 standard. I tried to use this feature with ifort 14, but observed strange behaviour. Following example should show this:

module mtypes
    implicit none

    type mytype
        integer, private :: nr
        contains

            final :: delete_mytype
            procedure :: print_mytype
    end type

    contains


!>      \brief Constructs a new mytype
!!      \return The created mytype
!>
        function init_mytype(number)
            type(mytype) :: init_mytype
            integer, intent(in) :: number
!            allocate(init_mytype)
            init_mytype = mytype(number)
            print *, 'init mytype', number
        end function

!>      \brief De-constructs a mytype object
!>
        subroutine delete_mytype(this)
            type(mytype) :: this   !< The mytype object that will be finalized
            print *, 'Deleted mytype!', this%nr
        end subroutine delete_mytype

!>      \brief Print something from mytype object
!>
        subroutine print_mytype(this)
            class(mytype) :: this   !< The mytype object that will print something
            print *, 'Print something from mytype!', this%nr
        end subroutine print_mytype


end module mtypes

program main

    use mtypes
    type(mytype) :: t1, t2

    call t1%print_mytype()
    call t2%print_mytype()

    t1 = mytype(1)
    call t1%print_mytype()
    t2 = init_mytype(2)
    call t2%print_mytype()

end program main

Within this complete example the type mytype is defined that only has one value nr. This type can be created using simple type constructor e.g. mytype(1) or the initialising function init_mytype. Also a subroutine print_mytype is defined that simply prints mytype%nr to stdout. Finally, the final routine delete_mytype should be used for finalisation, although in this example case it only prints some information to stdout.

This example gives following output:

 Print something from mytype!           0
 Print something from mytype!           0
 Deleted mytype!           0
 Print something from mytype!           1
 Deleted mytype!          -2
 init mytype           2
 Deleted mytype!           0
 Deleted mytype!           2
 Print something from mytype!           2
  • Line 1: Ok, t1 initialised with default value 0
  • Line 2: Ok, t2 initialised with default value 0
  • Line 3: Ok, after assignment of new object t1%mytype(1) the old version is deleted
  • Line 4: Ok, version with nr = 1 is printed
  • Line 5: Strange, where does a version with nr=-2 come from?
  • Line 6: Ok, version with nr = 2 is initialised
  • Line 7: Ok, after assignment of new object t2 = init_mytype(2) the old version is deleted
  • Line 8: Strange, t2 is finalized before call of t2%print_mytype()
  • Line 9: Strange, t2 is printed after finalisation

Is this strange behviour caused by some ifort bug or is this caused by wrong application of the finalization FORTRAN 2003 feature and I am doing something wrong?


回答1:


What appears strange is actually the result of the rules on finalization. In Fortran 2008 4.5.6.3 ("When finalization occurs") the prompts for finalization are given.

Before coming to those, a word about initialization. You say

Line 1: Ok, t1 initialised with default value 0

The derived type component nr doesn't have default initialization, and there's no explicit initialization for t1, so your statement isn't true. In fact, t1%nr is undefined at this point. 0 just happens to be the result. This is important, as we see later.

Your code, with comments about finalization:

t1 = mytype(1)          ! t1 finalized before assignment
call t1%print_mytype()
t2 = init_mytype(2)     ! t2 finalized before assignment, after function
                        ! init_mytype result finalized after assignment
call t2%print_mytype()
                        ! No finalization before END PROGRAM (4.5.6.4)

Your lines 8 and 9 unexpected behaviour are not strange. In particular, call t2%print_mytype() occurs after the two finalization calls in the statement t2=init_mytype(2).

Now, where does the finalization from line 5 come from? And why -2? Remember that there is no initialization? -2 is an allowed result if a finalization occurs for an entity without assignment. Which entity is finalized?

Look in the function init_mytype returning a result of type mytype:

function init_mytype(number)
  type(mytype) :: init_mytype    ! No initialization of result
  integer, intent(in) :: number

  init_mytype = mytype(number)   ! Result finalized before assignment
  print *, 'init mytype', number
end function

To conclude, the following prompts occur in this program:

  • When an intrinsic assignment statement is executed, the variable is finalized after evaluation of expr and before the definition of the variable.
  • If an executable construct references a function, the result is finalized after execution of the innermost executable construct containing the reference.

As an aside, if you look at the draft Fortran 2008 standard (such as I did when I mistakenly copied the wrong prompt in an earlier revision of this answer) you may think: why aren't the results of the structure constructor finalized? This should happen twice: once directly in the program, and once indirectly through the call to init_mytype. But we see no such effect.

Consider the interpretation request "How many times are constructed values finalized?" and the corrigendum. Constructor results are considered to be not finalized, correcting a mistake in Fortran 2003. This may be relevant, as you do ask about Fortran 2003 (although ifort clearly implements the new rules).



来源:https://stackoverflow.com/questions/29030497/finalisation-in-fortran-2003

易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!