# Eager finalization insertion location question

**URL:** <https://discourse.julialang.org/t/eager-finalization-insertion-location-question/103477>\
**Category:** General Usage\
**Created:** [September 3, 2023, 6:34am UTC](https://discourse.julialang.org/t/eager-finalization-insertion-location-question/103477 "2023-09-03T06:34:48Z")\
**Posts on this page:** 2\
**Page:** 1

<div class="post-metadata">

**Author:** ![Zentrik](https://sea2.discourse-cdn.com/julialang/user_avatar/discourse.julialang.org/zentrik/32/35409_2.png) [@Zentrik](https://discourse.julialang.org/u/Zentrik)\
**Post date:** [September 3, 2023, 6:34am UTC](https://discourse.julialang.org/t/eager-finalization-insertion-location-question/103477/1 "2023-09-03T06:34:48Z")

</div>

If I modify the example given here [https://github.com/JuliaLang/julia/pull/46651#issuecomment-1253471390](https://github.com/JuliaLang/julia/pull/46651#issuecomment-1253471390) to

```julia
const FINALIZATION_COUNT = Ref(0)
init_finalization_count!() = FINALIZATION_COUNT[] = 0
get_finalization_count() = FINALIZATION_COUNT[]
@noinline add_finalization_count!(x) = FINALIZATION_COUNT[] += x
@noinline Base.@assume_effects :nothrow safeprint(io::IO, x...) = (@nospecialize; print(io, x...))
@test Core.Compiler.is_finalizer_inlineable(Base.infer_effects(add_finalization_count!, (Int,)))

mutable struct DoAllocWithFieldInter
    x::Int
end
function register_finalizer!(obj::DoAllocWithFieldInter)
    finalizer(obj) do this
        add_finalization_count!(this.x)
    end
end

function cfg_finalization6(io)
    for i = -999:1000
        o = DoAllocWithFieldInter(0)
        register_finalizer!(o)
        safeprint(io, o.x, '\n')
    end
end

```

Let’s look at the ir code to see where the finalizer has been inserted

```julia
julia> ir = Base.code_ircode(cfg_finalization6, (IO,); optimize_until="SROA") |> only |> first
2 1 ─ goto #7 if not true │   
   2 ┄ %21 = φ (#1 => -999, #6 => %14)::Int64
   │ nothing::Tuple{Int64, Int64}   
   │ %3 = %21::Int64 │   
4 │ %4 = %new(Base.RefValue{Int64}, 0)::Base.RefValue{Int64}
5 │ nothing::Nothing │╻ register_finalizer!
6 │ %6 = Base.getfield(%4, :x)::Int64╻ getproperty
   │ %23 = Base.getfield(%4, :x)::Int64   
   │ invoke Main.add_finalization_count!(%23::Int64)::Int64
   │ invoke Main.safeprint(_2::IO, %6::Any, '\n'::Vararg{Any})::Any
13 │ %8 = (%3 === 1000)::Bool │╻╷ iterate
   └── goto #4 if not %8 ││  
   3 ─ goto #5 ││  
   4 ─ %11 = Base.add_int(%3, 1)::Int64 ││╻ +
   │ nothing::Tuple{Int64, Int64}╻ iterate
   └── goto #5 ││  
   5 ┄ %14 = φ (#4 => %11)::Int64 │   
   │ %22 = φ (#3 => true, #4 => false)::Bool
   │ nothing::Union{Nothing, Tuple{Int64, Int64}}
   │ %16 = %22::Bool │   
   │ %17 = Base.not_int(%16)::Bool │   
   └── goto #7 if not %17 │   
   6 ─ goto #2 │   
   7 ┄ return nothing 

```

It’s been inserted after the last `getfield` call but before the `safeprint`. Is this intended as I want to instead free a pointer in the finalizer and so cannot have any uses of it after the finalizer, e.g.

```julia
mutable struct UniquePointer{T} <: Ref{T}
    ptr::Ptr{T}
    function UniquePointer(ptr::Ptr{T}) where T
        self = new{T}(ptr)
        finalizer(free, self)
    end 
end
Base.@assume_effects :nothrow :notaskstate free(ptr) = Libc.free(ptr)
free(self::UniquePointer) = free(self.ptr)

```

I see in the SROA pass that the finalizer only seems to track uses for `getfield, setfield, isdefined` and `ccall`s. Would changing it to also track uses of its fields be desired.

---

<div class="post-metadata">

**Author:** ![Sukera](https://avatars.discourse-cdn.com/v4/letter/s/ce7236/32.png) [@Sukera](https://discourse.julialang.org/u/Sukera)\
**Post date:** [September 3, 2023, 6:56am UTC](https://discourse.julialang.org/t/eager-finalization-insertion-location-question/103477/2 "2023-09-03T06:56:54Z")

</div>

Yes, that is intended - the integer stored in your field is an `isbits` value, meaning it’s identity is defined by its bitpattern (the same is true for an explicitly stored `Ptr`). The only thing the finalizer itself cares about is whether the mutable struct itself is no longer needed - which is the case after the field has been accessed and its value has been retrieved.

It is your responsibility to make sure the object referred to by the pointer is kept alive while its memory is being accessed through the pointer, via `GC.@preserve` or otherwise keeping a live reference around. Eagerly `free`ing the pointer once the struct it’s contained in is no longer referenced may lead to use after free.
