- Mark as New
- Bookmark
- Subscribe
- Mute
- Subscribe to RSS Feed
- Permalink
- Report Inappropriate Content
Hello,
I don't know how far ifort's support for type-bound final bindings goes right now, but here is some strange behaviour:
[fortran]
module m
implicit none
type :: derived_type
! allocatable component causes rerunning the finalizer
integer, allocatable :: alloc_comp
! value 99 indicates that the finalizer already went over this
integer :: finalized = 0
! identification
character :: ID = '?'
contains
final :: finalize
end type
contains
! finalizer
subroutine finalize(arg)
type(derived_type) :: arg
print *, 'run finalizer on ID = ', arg%ID, ':'
if (arg%finalized == 99) then
print *, '...finalizing an already finalized object!'
end if
arg%finalized = 99
end subroutine
! main
subroutine test_finalizer()
type(derived_type), allocatable :: my_derived_alloc ! (1)
type(derived_type) :: my_derived ! (2)
! mark local variable that sould be finalized
my_derived%ID = 'X'
! additional code and allocations involving both variables
! does not change behaviour (as far as I tested it)
end subroutine
end module
program p
use m
implicit none
call test_finalizer()
end program
[/fortran]
Results:
- comment out (1): single finalization on local variable [OK]
- comment out (2): no finalization (no allocation) [OK]
- interchanging lines (1) and (2): single run of finalizer [STRANGE...]
- both uncommented: double finalization on loval variable [FAIL?]
General question:
- Is there ever a (legal) situation where multiple finalizations of the same object might happen?
- Are there any situations where finalization nessecary to deallocate derived-type allocatable components?
(Or is that taken care of in in every possible situation automatically?)
Thank you for advice and comments,
Ferdinand
PS: my ifort version is 14.0.0
Link Copied
- Mark as New
- Bookmark
- Subscribe
- Mute
- Subscribe to RSS Feed
- Permalink
- Report Inappropriate Content
Ferdinand T. wrote:
General question:
- Is there ever a (legal) situation where multiple finalizations of the same object might happen?
- Are there any situations where finalization nessecary to deallocate derived-type allocatable components?
(Or is that taken care of in in every possible situation automatically?)
AFAIK, finalization is not necessary for allocatable derived types that only have allocatable components. I believe that whenever an object with the allocatable attribute goes out of scope the standard dictates that it be deallocated. So, for most use cases, you will not need final procedures if your derived types are allocatable.
Can you please include the commands you used to compile the code, and the output?
- Mark as New
- Bookmark
- Subscribe
- Mute
- Subscribe to RSS Feed
- Permalink
- Report Inappropriate Content
Hello Zaak,
thank you for the reply! I just recompiled my sample code with ifort version 14.0.1:
Commands (no flags used):
ifort finalization_twice.f90
./a.out
(the source file's name is finalization_twice.f90)
Output:
- comment out (1): single finalization on local variable [OK]
run finalizer on ID = X: - comment out (2): no finalization (no allocation) [OK]
(note: also commented out the line my_derived%ID = 'X')
- no outpout - - interchanging lines (1) and (2): single run of finalizer [STRANGE...]
run finalizer on ID = X: - both uncommented: double finalization on loval variable [FAIL?]
run finalizer on ID = X:
run finalizer on ID = X:
...finalizing an already finalized object!
In the last case (e.g. the unmodified sample program as stated above), the output indicates that the finalizer is invoked twice.
Concerning the general question on finalization of allocatable components: Here is a sample program that shows a memory leak if no finalization is used (probably a compiler issue, then?)
[fortran]
module m
implicit none
! extendable type
type :: component_type
integer(4) :: some_field ! cause 4-bit leak
end type
! container with polymorphic component
type :: derived_type
class(component_type), allocatable :: alloc_comp ! use 'type' and leak vanishes
contains
!final :: finalize_derived ! comment in and leak vanishes
end type
contains
! finalizer to deallocate components
subroutine finalize_derived(arg)
type(derived_type) :: arg
if (allocated(arg%alloc_comp)) deallocate(arg%alloc_comp)
end subroutine
! contructor to allocate components
function create_derived()
type(derived_type) :: create_derived
allocate(create_derived%alloc_comp)
end function
end module
program p
use m
implicit none
type(derived_type) :: my_derived
! derived type assignment causes memory leak (an alloc_comp gets lost?)
my_derived = create_derived()
end program
[/fortran]
compilation commands:
ifort finalization_twice.f90
valgrind invocation:
valgrind --tool=memcheck ./a.out
valgrind output:
==3888== LEAK SUMMARY:
==3888== definitely lost: 4 bytes in 1 blocks
==3888== indirectly lost: 0 bytes in 0 blocks
==3888== possibly lost: 0 bytes in 0 blocks
==3888== still reachable: 36 bytes in 2 blocks
==3888== suppressed: 0 bytes in 0 blocks
That behaviour causes heavy memory leaks in my original code, which I can only avoid using finalizers.
Best regards, Ferdinand
- Mark as New
- Bookmark
- Subscribe
- Mute
- Subscribe to RSS Feed
- Permalink
- Report Inappropriate Content
The double finalization has been escalated as issue DPD200249474. I am somewhat surprised by this as we did a lot of work on finalization lists in 14.0. Obviously not enough.
I will also look at your memory leak example.
- Mark as New
- Bookmark
- Subscribe
- Mute
- Subscribe to RSS Feed
- Permalink
- Report Inappropriate Content
The memory leak is escalated as issue DPD200249476. Note that the language specifies that no finalization or automatic deallocation of my_derived is done at the end of the program, so there will always be one "leak", but the alloc_comp of the function result should have been deallocated after the assignment.
- Mark as New
- Bookmark
- Subscribe
- Mute
- Subscribe to RSS Feed
- Permalink
- Report Inappropriate Content
Steve, thank you for investigating these issues. The leak-example might be over-simplified, but moving the leaky code into a subroutine doesn't change the behaviour. My experience is that valgrind identifies allocations from the main program as 'still reachable' (since no automatic deallocation is done), but never as a loss.
Regards, Ferdinand
- Mark as New
- Bookmark
- Subscribe
- Mute
- Subscribe to RSS Feed
- Permalink
- Report Inappropriate Content
Right - I simply mentioned the main program thing because valgrind should show one leak. There shouldn't be two.
- Mark as New
- Bookmark
- Subscribe
- Mute
- Subscribe to RSS Feed
- Permalink
- Report Inappropriate Content
This has been fixed in our sources. I expect the fix to appear in a release later this year.
- Mark as New
- Bookmark
- Subscribe
- Mute
- Subscribe to RSS Feed
- Permalink
- Report Inappropriate Content
Steve, back on #5 "Note that the language specifies that no finalization or automatic deallocation of my_derived is done at the end of the program"
In the sample code listing my_derived was not declared itself as allocatable (though a member variable within was).
What is the reason for no finalization?
a) lack of allocatable on my_derived?
b) the fact that it exists in the scope of PROGRAM (iow, had it appeared in a subroutine, the member variable would have been deleted)?
Jim Dempsey
- Mark as New
- Bookmark
- Subscribe
- Mute
- Subscribe to RSS Feed
- Permalink
- Report Inappropriate Content
b
"If image execution is terminated, either by an error (e.g. an allocation failure) or by execution of a stop-stmt , error-stop-stmt , or end-program-stmt , entities existing immediately prior to termination are not finalized."

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