- Mark as New
- Bookmark
- Subscribe
- Mute
- Subscribe to RSS Feed
- Permalink
- Report Inappropriate Content
A Struct Testype2 contained the subobject of Testype1. I defined the final procedure which contain a write statement for both the two Type.
case1: I define a allocatable varaiable of testype2, after I deallocate it, the final procedure of the two type both invoked. I think this is the right result.
case2: I define a allocatable array of testype2 which contained 10 items, after I deallocate it, the testype1 final procedure was invoked 10 times, but the testype2 final procedure wasn't invoked. I don't know why.
can anybody help me? Steve~ Help~~
case1 code:
[fortran]
module mod1
implicit none
type :: testype1
integer :: i
contains
procedure :: PrintTT1
Final :: FinalTT1
end type testype1
type :: testype2
type(testype1) :: tt1
contains
Final :: FinalTT2
end type testype2
contains
subroutine PrintTT1(this)
class(testype1) :: this
write(*,*) "this.x=", this.i
end subroutine PrintTT1
subroutine FinalTT1(this)
type(testype1) :: this
write(*,*) "Final Testype1"
end subroutine FinalTT1
subroutine FinalTT2(this)
type(testype2) :: this
write(*,*) "Final Testype2"
end subroutine FinalTT2
end module mod1
subroutine TestFinal()
use mod1
type(testype2), allocatable :: tt2
allocate(tt2)
tt2.tt1.i = 3
call tt2.tt1.PrintTT1()
deallocate(tt2)
end subroutine TestFinal
program main
implicit none
call TestFinal()
end program main
[/fortran]
case2 code:
[fortran]
module mod1
implicit none
type :: testype1
integer :: i
contains
procedure :: PrintTT1
Final :: FinalTT1
end type testype1
type :: testype2
type(testype1) :: tt1
contains
Final :: FinalTT2
end type testype2
contains
subroutine PrintTT1(this)
class(testype1) :: this
write(*,*) "this.x=", this.i
end subroutine PrintTT1
subroutine FinalTT1(this)
type(testype1) :: this
write(*,*) "Final Testype1"
end subroutine FinalTT1
subroutine FinalTT2(this)
type(testype2) :: this
write(*,*) "Final Testype2"
end subroutine FinalTT2
end module mod1
subroutine TestFinal()
use mod1
type(testype2), allocatable, dimension(:) :: tt2
integer :: m
allocate(tt2(10))
do m=1,10
tt2(m).tt1.i = m
call tt2(m).tt1.PrintTT1()
end do
deallocate(tt2)
end subroutine TestFinal
program main
implicit none
call TestFinal()
end program main
[/fortran]
Link Copied
- Mark as New
- Bookmark
- Subscribe
- Mute
- Subscribe to RSS Feed
- Permalink
- Report Inappropriate Content
Resolution of final procedures is based on the rank of the thing being finalised. In case 2, tt2 is a rank one object. The only procedure for finalisation of objects of the type of tt2 (testtype2) is a non-elemental and takes a scalar dummy argument - this doesn't match the rank of tt2 hence no final procedure is called.
Inside the type testtype2 is a scalar component tt1 of type testtype1. Thta type has a final binding that takes a scalar dummy argument. This matches the rank of the ten scalar things being finalised and hence it is called - once for each scalar thing.
Note that if your final procedure was elemental, it would match an object being finalised of any rank. External IO in such a procedure would require support for F2008's IMPURE procedure attribute. Alternatively you can create specific bindings for each rank that you want to support.
- Mark as New
- Bookmark
- Subscribe
- Mute
- Subscribe to RSS Feed
- Permalink
- Report Inappropriate Content
Thanks lanH.
your explanation was clear enough that I thought I got it. However, I have one more question:
in case 2, although the final procedure of testype2 was not invoked, but I think the memory space occupied by the variable tt2 was deallocated, am I right?
- Mark as New
- Bookmark
- Subscribe
- Mute
- Subscribe to RSS Feed
- Permalink
- Report Inappropriate Content
Yes. Deallocation might result in finalisation, but finalisation is not a requirement for deallocation.
- Mark as New
- Bookmark
- Subscribe
- Mute
- Subscribe to RSS Feed
- Permalink
- Report Inappropriate Content
lanH, if i change tt1 to allocatable, I monitor the memory, I find the tt1 is released, but the final procedure of testype1 was not invoked. How should i change the final procedure to let the testype1 final procedure invoke automaticaly? Thank you!
[fortran]
module mod1
implicit none
type :: testype1
integer, dimension(10000000) :: i
contains
final :: FinalTT1
end type testype1
type :: testype2
type(testype1), allocatable :: tt1
contains
final :: FinalTT2
end type testype2
contains
subroutine FinalTT1(this)
type(testype1), intent(in) :: this
write(*,*) "Final Testype1"
end subroutine FinalTT1
subroutine FinalTT2(this)
type(testype2), intent(in) :: this
write(*,*) "Final Testype2"
end subroutine FinalTT2
end module mod1
subroutine Foo()
use mod1
implicit none
type(testype2), pointer :: tt2
allocate(tt2)
allocate(tt2.tt1)
tt2.tt1.i = 4
deallocate(tt2)
end subroutine Foo
program main
implicit none
call Foo()
end program main
[/fortran]
- Mark as New
- Bookmark
- Subscribe
- Mute
- Subscribe to RSS Feed
- Permalink
- Report Inappropriate Content
That's probably a compiler bug. I've encountered a few gaps with finalization support.
Note that the standard structure reference syntax uses "%", not ".".
- Mark as New
- Bookmark
- Subscribe
- Mute
- Subscribe to RSS Feed
- Permalink
- Report Inappropriate Content
lanH, How should i deal with such case. If I deallocate the tt1 in the testype2 final procedure explicitly, then the final procedure of testype1 would be invoked. So, was the explicitlt deallocate in final procedure always be the best option?
- Mark as New
- Bookmark
- Subscribe
- Mute
- Subscribe to RSS Feed
- Permalink
- Report Inappropriate Content
It depends on what you are trying to do.
There is no need to explicitly deallocate allocatable components or allocatable variables (unless you are about to reallocate them to something different). tt1 is an allocatable component. When its parent tt2 is deallocated, tt1 will also be deallocated. The final procedure for either tt1 or tt2 need not play any role in this.
If you have pointer components or pointer variables, the first question I would be asking is ... "why?".
The last time I checked in any detail was with some version of 13.0 - but I currently avoid relying on finalization with ifort because there were too many gaps. If I need to clean up pointers or whatever in derived types then I write and explicitly call a procedure that does that clean-up. That procedure is written in a way that means that in the future it may easily be made a final binding. This is a separate issue to deallocation of allocatable components, which is robust unless you are playing with polymorphic components.

- Subscribe to RSS Feed
- Mark Topic as New
- Mark Topic as Read
- Float this Topic for Current User
- Bookmark
- Subscribe
- Printer Friendly Page