# Can calling finalize lead to a double free?

**URL:** https://discourse.julialang.org/t/can-calling-finalize-lead-to-a-double-free/116612
**Category:** General Usage
**Tags:** question, finalization
**Created:** [July 4, 2024, 3:35am UTC](https://discourse.julialang.org/t/can-calling-finalize-lead-to-a-double-free/116612 "2024-07-04T03:35:50Z")
**Posts on this page:** 5
**Page:** 1

<div class="post-metadata">

### Author: ![nhz2](https://sea2.discourse-cdn.com/julialang/user_avatar/discourse.julialang.org/nhz2/32/44428_2.png) [@nhz2](https://discourse.julialang.org/u/nhz2)
#### Post date: [July 4, 2024, 3:35am UTC](https://discourse.julialang.org/t/can-calling-finalize-lead-to-a-double-free/116612/1 "2024-07-04T03:35:50Z")

</div>

Are finalizers guaranteed to only run at most one time? Is there any way for a finalizer to somehow get called twice, for example, if `finalize` is [called in multiple other finalizers](https://discourse.julialang.org/t/calling-finalize-from-running-finalizer/115365), or manually called in different threads?

I am trying to manually free memory not owned by Julia when I know it won’t be used later, but also have a finalizer as a fallback to avoid memory leaks.

---

<div class="post-metadata">

### Author: ![nhz2](https://sea2.discourse-cdn.com/julialang/user_avatar/discourse.julialang.org/nhz2/32/44428_2.png) [@nhz2](https://discourse.julialang.org/u/nhz2)
#### Post date: [July 4, 2024, 3:53am UTC](https://discourse.julialang.org/t/can-calling-finalize-lead-to-a-double-free/116612/2 "2024-07-04T03:53:09Z")

</div>

I see there is an issue to support this sort of thing more generally in [Provide a julia alternative of `pthread_once` · Issue #54042 · JuliaLang/julia · GitHub](https://github.com/JuliaLang/julia/issues/54042)

But maybe Julia already guarantees this for finalizers?

---

<div class="post-metadata">

### Author: ![PatrickHaecker](https://sea2.discourse-cdn.com/julialang/user_avatar/discourse.julialang.org/patrickhaecker/32/222891_2.png) [@PatrickHaecker](https://discourse.julialang.org/u/PatrickHaecker)
#### Post date: [July 4, 2024, 6:04am UTC](https://discourse.julialang.org/t/can-calling-finalize-lead-to-a-double-free/116612/3 "2024-07-04T06:04:13Z")

</div>

In my experiments I have never seen `finalize` running more than once per registration and I guess that it’s mutli-threading safe, but I haven’t checked the code. That being said, you probably (I haven’t tested that) can run it multiple times if you register it multiple times. Note, that you can register during the `finalize` call so you can decide at the latest possible point if you want to have it run again in the future (however that could possibly lead to a problematic looping behavior).

However, not using `finalize` can still be beneficial due to being deterministic and low-latency (probably also leading to a better memory locality usage pattern). You can use a `do` block to have it called semi-automatically (automatically from the caller’s perspective). If you want to mostly ensure that the memory gets freed, you can use some parts of a `try-catch-finally-else` block and probably hide that behind a function, too.

If you like the ease of `finalize` to contain all the relevant state needed for freeing the memory, you can create an anonymous function containing that state and save it as a field in your struct and call that with the mentioned mechanisms when you know that you do not need it anymore.

---

<div class="post-metadata">

### Author: ![foobar\_lv2](https://avatars.discourse-cdn.com/v4/letter/f/ee59a6/32.png) [@foobar\_lv2](https://discourse.julialang.org/u/foobar_lv2)
#### Post date: [July 4, 2024, 10:16am UTC](https://discourse.julialang.org/t/can-calling-finalize-lead-to-a-double-free/116612/4 "2024-07-04T10:16:31Z")

</div>

You can read the code [here](https://github.com/JuliaLang/julia/blob/34bacaa6e49a6252f9ae9c7896a6f4d043578d02/src/gc.c#L592).

So I think the answer is no: Calling finalize manually can lead to use-after-free but not to double-free.

The protecting lock is global. So you may have contention if you call lots of finalizers manually from many threads. But the critical section doesn’t include the actual finalization code.

On the other hand, if I understand the code right, you can install many finalizers on many threads without contention (i.e. multi-threaded BigInt code doesn’t suck).

---

<div class="post-metadata">

### Author: ![mkitti](https://sea2.discourse-cdn.com/julialang/user_avatar/discourse.julialang.org/mkitti/32/12459_2.png) [@mkitti](https://discourse.julialang.org/u/mkitti)
#### Post date: [July 4, 2024, 10:44am UTC](https://discourse.julialang.org/t/can-calling-finalize-lead-to-a-double-free/116612/5 "2024-07-04T10:44:55Z")

</div>

If the pointer is stored in a mutable object, I would set the pointer to `C_NULL` immediately after freeing it to prevent it from being freed again. The finalizer should check if the pointer is null before trying tk free.
