# When a final subroutine is called

**URL:** <https://fortran-lang.discourse.group/t/when-a-final-subroutine-is-called/3246>\
**Category:** Uncategorized\
**Created:** [April 15, 2022, 9:38pm UTC](https://fortran-lang.discourse.group/t/when-a-final-subroutine-is-called/3246 "2022-04-15T21:38:55Z")\
**Posts on this page:** 9\
**Page:** 1

<div class="post-metadata">

**Author:** ![Beliavsky](https://avatars.discourse-cdn.com/v4/letter/b/ba8739/32.png) [@Beliavsky](https://fortran-lang.discourse.group/u/Beliavsky)\
**Post date:** [April 15, 2022, 9:38pm UTC](https://fortran-lang.discourse.group/t/when-a-final-subroutine-is-called/3246/1 "2022-04-15T21:38:55Z")

</div>

For Intel Fortran and gfortran, two cases where a FINAL subroutine of a derived type are called are when a local derived type goes out of scope in a procedure or when a local variable that is not allocatable or a pointer goes out of scope in a block (code below). I thought that the final subroutine would also be called when exiting blocks b2, b3, or b4. The Fortran standard in section “7.5.6.3 When finalization occurs” says

> When a pointer is deallocated its target is finalized. When an allocatable entity is deallocated, it is finalized unless it is the variable in an intrinsic assignment statement or a subobject thereof. If an error condition occurs during deallocation, it is processor dependent whether finalization occurs.

```auto
module m
!
type :: vec
   real, pointer :: x(:) => null()
   contains
      final :: destructor
end type vec
!
contains
!
subroutine destructor(v)
type(vec) :: v
print*,"entering destructor, associated(v%x) =",associated(v%x)
if (associated(v%x)) deallocate (v%x)
print*,"leaving destructor, associated(v%x) =",associated(v%x)
end subroutine destructor
!
subroutine sub_alloc()
type(vec) :: v
allocate (v%x(2))
v%x = [10.0,20.0]
print*,"in sub_alloc, v%x =",v%x
end subroutine sub_alloc
!
subroutine sub_automatic()
type(vec) :: v
allocate (v%x(2))
v%x = [10.0,20.0]
print*,"in sub_automatic, v%x =",v%x
end subroutine sub_automatic
!
end module m
!
program main
use m, only: vec, sub_alloc, sub_automatic
implicit none
b1: block
   type(vec) :: v
   allocate (v%x(3))
   print*,"exiting b1"
end block b1
b2: block
   type(vec), allocatable :: v(:)
   allocate (v(3))
   print*,"exiting b2"
end block b2
b3: block
   type(vec), allocatable :: v(:)
   allocate (v(3))
   deallocate (v)
   print*,"exiting b3"
end block b3
b4: block
   type(vec), pointer :: v(:) => null()
   allocate (v(3))
   print*,"exiting b4"
end block b4
print*,"calling sub_alloc()"
call sub_alloc()
print*,"calling sub_automatic()"
call sub_automatic()
end program main

```

Output:

```auto
exiting b1
 entering destructor, associated(v%x) = T
 leaving destructor, associated(v%x) = F
 exiting b2
 exiting b3
 exiting b4
 calling sub_alloc()
 in sub_alloc, v%x = 10.00000 20.00000    
 entering destructor, associated(v%x) = T
 leaving destructor, associated(v%x) = F
 calling sub_automatic()
 in sub_automatic, v%x = 10.00000 20.00000    
 entering destructor, associated(v%x) = T
 leaving destructor, associated(v%x) = F

```

---

<div class="post-metadata">

**Author:** ![FortranFan](https://avatars.discourse-cdn.com/v4/letter/f/96bed5/32.png) [@FortranFan](https://fortran-lang.discourse.group/u/FortranFan)\
**Post date:** [April 15, 2022, 11:05pm UTC](https://fortran-lang.discourse.group/t/when-a-final-subroutine-is-called/3246/3 "2022-04-15T23:05:17Z")

</div>

One can think of `FINAL` as a generic interface to which one can either establish finalizer procedures for the ranks of objects to be finalized or an `ELEMENTAL’ procedure.

As shown in the original post, the generic interface only has finalizer for a rank-0 (scalar) object.

---

<div class="post-metadata">

**Author:** ![FortranFan](https://avatars.discourse-cdn.com/v4/letter/f/96bed5/32.png) [@FortranFan](https://fortran-lang.discourse.group/u/FortranFan)\
**Post date:** [April 15, 2022, 11:42pm UTC](https://fortran-lang.discourse.group/t/when-a-final-subroutine-is-called/3246/5 "2022-04-15T23:42:38Z")

</div>

> [@septc](#):
>
> wonder what is the use case for defining rank-dependent destructors

More flexibility that somehow made it into the standard with feature.

Consider abstraction toward vector calculus: conceivably, the finalization instructions toward objects of vector fields in one’s domain might differ with dimensionality. The existing semantics allows, at least in principle, the handling of such needs.

Practically though an `ELEMENTAL` finalizer might suffice in most situation.

---

<div class="post-metadata">

**Author:** ![Beliavsky](https://avatars.discourse-cdn.com/v4/letter/b/ba8739/32.png) [@Beliavsky](https://fortran-lang.discourse.group/u/Beliavsky)\
**Post date:** [April 15, 2022, 11:51pm UTC](https://fortran-lang.discourse.group/t/when-a-final-subroutine-is-called/3246/7 "2022-04-15T23:51:29Z")

</div>

Thanks @FortranFan. I made the destructor impure elemental. For the code

```auto
module m
!
type :: vec
   real, pointer :: x(:) => null()
   contains
      final :: destructor
end type vec
!
contains
!
impure elemental subroutine destructor(v)
type(vec), intent(in out) :: v
logical :: assoc_init
assoc_init = associated(v%x)
if (assoc_init) deallocate (v%x)
write (*,*) "leaving destructor, assoc_init, assoc_final =",assoc_init,associated(v%x)
end subroutine destructor
!
subroutine sub_alloc()
type(vec) :: v
allocate (v%x(2))
v%x = [10.0,20.0]
print*,"in sub_alloc, v%x =",v%x
end subroutine sub_alloc
!
subroutine sub_automatic()
type(vec) :: v
allocate (v%x(2))
v%x = [10.0,20.0]
print*,"in sub_automatic, v%x =",v%x
end subroutine sub_automatic
!
end module m
!
program main
use m, only: vec, sub_alloc, sub_automatic
implicit none
b1: block
   type(vec) :: v
   allocate (v%x(2))
   print*,"exiting b1 for scalar v"
end block b1
b2: block
   type(vec), allocatable :: v(:)
   allocate (v(2))
   print*,"exiting b2, size(v) =",size(v)
end block b2
b3: block
   type(vec), allocatable :: v(:)
   allocate (v(2))
   deallocate (v)
   print*,"exiting b3, allocated(v) =",allocated(v)
end block b3
b4: block
   type(vec), pointer :: v(:) => null()
   allocate (v(2))
   print*,"exiting b4, size(v)=",size(v)
end block b4
print*,"calling sub_alloc()"
call sub_alloc()
print*,"calling sub_automatic()"
call sub_automatic()
end program main

```

I get output with gfortran and Intel Fortran of

```auto
 exiting b1 for scalar v
 leaving destructor, assoc_init, assoc_final = T F
 exiting b2, size(v) = 2
 leaving destructor, assoc_init, assoc_final = F F
 leaving destructor, assoc_init, assoc_final = F F
 leaving destructor, assoc_init, assoc_final = F F
 leaving destructor, assoc_init, assoc_final = F F
 exiting b3, allocated(v) = F
 exiting b4, size(v)= 2
 calling sub_alloc()
 in sub_alloc, v%x = 10.0000000 20.0000000    
 leaving destructor, assoc_init, assoc_final = T F
 calling sub_automatic()
 in sub_automatic, v%x = 10.0000000 20.0000000    
 leaving destructor, assoc_init, assoc_final = T F

```

When exiting b2, I wonder why the destructor is called 4 times rather than twice, when `size(v) = 2`.

---

<div class="post-metadata">

**Author:** ![FortranFan](https://avatars.discourse-cdn.com/v4/letter/f/96bed5/32.png) [@FortranFan](https://fortran-lang.discourse.group/u/FortranFan)\
**Post date:** [April 16, 2022, 3:14am UTC](https://fortran-lang.discourse.group/t/when-a-final-subroutine-is-called/3246/8 "2022-04-16T03:14:05Z")

</div>

> [@Beliavsky](#):
>
> When exiting b2, I wonder why the destructor is called 4 times rather than twice, when `size(v) = 2` .

You’re dealing with the artifacts of processor-dependent actions leading to your puzzlement with the program behavior. Try the following:

> **Click to see**
>
> ```fortran
> module m
> !
> type :: vec
> character(len=20) :: id = ""
> real, pointer :: x(:) => null()
> contains
> final :: destructor
> end type vec
> !
> contains
> !
> impure elemental subroutine destructor(v)
> type(vec), intent(in out) :: v
> logical :: assoc_init
> assoc_init = associated(v%x)
> if (assoc_init) deallocate (v%x)
> write (*,*) "leaving destructor, id, assoc_init, assoc_final = ",trim(v%id), assoc_init,associated(v%x)
> end subroutine destructor
> !
> subroutine sub_alloc()
> type(vec) :: v
> allocate (v%x(2))
> v%x = [10.0,20.0]
> v%id = "sub_alloc"
> print*,"in sub_alloc, v%x =",v%x
> end subroutine sub_alloc
> !
> subroutine sub_automatic()
> type(vec) :: v
> allocate (v%x(2))
> v%x = [10.0,20.0]
> v%id = "sub_automatic"
> print*,"in sub_automatic, v%x =",v%x
> end subroutine sub_automatic
> !
> end module m
> !
> program main
> use m, only: vec, sub_alloc, sub_automatic
> implicit none
> b1: block
> type(vec) :: v
> v%id = "b1"
> allocate (v%x(2))
> print*,"exiting b1 for scalar v"
> end block b1
> b2: block
> type(vec), allocatable :: v(:)
> allocate (v(2))
> v(1)%id = "b2_1" ; v(2)%id = "b2_2"
> print*,"exiting b2, size(v) =",size(v)
> end block b2
> print *
> b3: block
> type(vec), allocatable :: v(:)
> allocate (v(2))
> v(1)%id = "b3_1" ; v(2)%id = "b3_2"
> deallocate (v)
> print*,"exiting b3, allocated(v) =",allocated(v)
> end block b3
> b4: block
> type(vec), pointer :: v(:) => null()
> allocate (v(2))
> v(1)%id = "b4_1" ; v(2)%id = "b4_2"
> print*,"exiting b4, size(v)=",size(v)
> end block b4
> print*,"calling sub_alloc()"
> call sub_alloc()
> print*,"calling sub_automatic()"
> call sub_automatic()
> end program main
> 
> ```

Attention also to anyone interested in finalization

- Employ some suitable identifier scheme for the objects toward your book-keeping; a simple `id` component is used in the code above,

and/or `BLOCK` constructs in simple unit tests on Windows:

- Do the equivalent of a system flush/clear message queue in between `BLOCK` constructs to keep the instructions in order if that is of interest; shown here with a simple `PRINT` statement.

---

<div class="post-metadata">

**Author:** ![DavidB](https://avatars.discourse-cdn.com/v4/letter/d/76d3ee/32.png) [@DavidB](https://fortran-lang.discourse.group/u/DavidB)\
**Post date:** [June 21, 2023, 1:11pm UTC](https://fortran-lang.discourse.group/t/when-a-final-subroutine-is-called/3246/9 "2023-06-21T13:11:16Z")

</div>

@FortranFan Thank you. I was struggling destructors and found your example code. I doubt I would have ever thought about `impure elemental `.

---

<div class="post-metadata">

**Author:** ![FortranFan](https://avatars.discourse-cdn.com/v4/letter/f/96bed5/32.png) [@FortranFan](https://fortran-lang.discourse.group/u/FortranFan)\
**Post date:** [June 21, 2023, 1:34pm UTC](https://fortran-lang.discourse.group/t/when-a-final-subroutine-is-called/3246/10 "2023-06-21T13:34:25Z")

</div>

👍

---

<div class="post-metadata">

**Author:** ![PierU](https://yyz2.discourse-cdn.com/free1/user_avatar/fortran-lang.discourse.group/pieru/32/1848_2.png) [@PierU](https://fortran-lang.discourse.group/u/PierU)\
**Post date:** [July 5, 2023, 2:13pm UTC](https://fortran-lang.discourse.group/t/when-a-final-subroutine-is-called/3246/11 "2023-07-05T14:13:49Z")

</div>

> [@DavidB](#):
>
> @FortranFan Thank you. I was struggling destructors and found your example code. I doubt I would have ever thought about `impure elemental `.

Thiis makes sense once you know, but it’s definitely not intuitive…

---

<div class="post-metadata">

**Author:** ![DavidB](https://avatars.discourse-cdn.com/v4/letter/d/76d3ee/32.png) [@DavidB](https://fortran-lang.discourse.group/u/DavidB)\
**Post date:** [July 5, 2023, 2:21pm UTC](https://fortran-lang.discourse.group/t/when-a-final-subroutine-is-called/3246/12 "2023-07-05T14:21:26Z")

</div>

> [@PierU](#):
>
> Thiis makes sense once you know, but it’s definitely not intuitive…

Yes. It was blinding obvious in hindsight. I understand and use `impure elemental`.
