# High memory usage when creating lots of temporary C++ objects

**URL:** <https://discourse.julialang.org/t/high-memory-usage-when-creating-lots-of-temporary-c-objects/135399>\
**Category:** General Usage\
**Tags:** memory, cxxwrap\
**Created:** [February 2, 2026, 8:48am UTC](https://discourse.julialang.org/t/high-memory-usage-when-creating-lots-of-temporary-c-objects/135399 "2026-02-02T08:48:04Z")\
**Posts on this page:** 10\
**Page:** 1

<div class="post-metadata">

**Author:** ![Vasily\_Pisarev](https://sea2.discourse-cdn.com/julialang/user_avatar/discourse.julialang.org/vasily_pisarev/32/7929_2.png) [@Vasily\_Pisarev](https://discourse.julialang.org/u/Vasily_Pisarev)\
**Post date:** [February 2, 2026, 8:48am UTC](https://discourse.julialang.org/t/high-memory-usage-when-creating-lots-of-temporary-c-objects/135399/1 "2026-02-02T08:48:05Z")

</div>

I found out that creating lots of temporary C++ objects through CxxWrap takes a lot of memory (duh!) and does not return that memory to the system after GC.  
My use case is [this package](https://github.com/vvpisarev/VoroPlusPlus.jl) wrapping Voro++ library. Logically, iterating over a Voronoi tessellation there is meant to yield a Voronoi cell object on each iteration, and ideally I’d like the objects to be independent.  
That rises an issue as each of the objects does not get immediately GC’ed if unused after the current iteration, so that memory allocation rises. Then at a later point GC `delete`s the objects. But the `delete` operator does not return the memory to the system but instead returns it to some memory pool for reuse. So, even though the objects get GC’ed at some point, the memory they allocated isn’t returned to the system.  
That alone isn’t a huge problem, the problem arises when I run multiple loops creating such objects. Then, if the GC does not run after each loop, the allocated memory piles up and can consume all RAM.

So, I’m wondering how to make the object get collected as soon as possible after they are not needed?

The solution I have so far is to make two iterators, a “safe” one which allocates fresh objects, and “unsafe” which reuses a single objects for iteration. My feeling, though, is that neither is user-friendly. The first one because it can quickly lead to OOM, especially in an exploratory environment where a user tries the same thing with minor modifications over and over again. The second one needs a user to be concious that the results of iteration are not independent.

Am I missing a good third way to do the right thing without risking OOM?

---

<div class="post-metadata">

**Author:** ![barche](https://sea2.discourse-cdn.com/julialang/user_avatar/discourse.julialang.org/barche/32/79_2.png) [@barche](https://discourse.julialang.org/u/barche)\
**Post date:** [February 2, 2026, 8:50pm UTC](https://discourse.julialang.org/t/high-memory-usage-when-creating-lots-of-temporary-c-objects/135399/2 "2026-02-02T20:50:19Z")

</div>

What is the type of the iterator that you are using? If this type needs to be wrapped like a normal “opaque” C++ type, this will indeed allocate for every iterator that is produced. If you could somehow rewrite this to return only references and primitive types from C++, then there should be no heap allocated Julia objects involved.

---

<div class="post-metadata">

**Author:** ![Vasily\_Pisarev](https://sea2.discourse-cdn.com/julialang/user_avatar/discourse.julialang.org/vasily_pisarev/32/7929_2.png) [@Vasily\_Pisarev](https://discourse.julialang.org/u/Vasily_Pisarev)\
**Post date:** [February 3, 2026, 8:56am UTC](https://discourse.julialang.org/t/high-memory-usage-when-creating-lots-of-temporary-c-objects/135399/3 "2026-02-03T08:56:36Z")

</div>

The objects are composite structures having some nested arrays inside (as I am not related to the original library devs, I only have limited high-level understanding of the inner structure), in total like 200 kB per object.  
Actually, the Julia-side allocations are not a problem, the memory is taken on the C++ side. Since GC happens only every so often, a lot of objects are allocated, and I think Julia runtime is unaware of the memory consumption. What happens is that I can iterate multiple times over a container having several thousand particles without a single GC sweep, while the memory on the C++ side grows substantially.  
I think the root of the problem is the same as [here](https://github.com/JuliaLang/julia/issues/42566#issuecomment-941239792). But the additional catch is that Julia runtime seems to be unaware of the C++ heap size and thus miscalculates when to run GC. At least in my experimenting, the system easily reached OOM (at 45 GB Julia usage) without a GC sweep.  
If I add `GC.gc()` on iterator exhaustion, the memory taken is only one loop’s worth, which is understandable: temp objects stay uncollected until the end of the loop, then GC deletes them, memory stays reserved by C++ runtime but at least does on subsequent iterations.

On returning references: that might be helpful but I am not an expert. Would that need support from the wrapped C++ library to ensure correct memory management?

---

<div class="post-metadata">

**Author:** ![barucden](https://sea2.discourse-cdn.com/julialang/user_avatar/discourse.julialang.org/barucden/32/26154_2.png) [@barucden](https://discourse.julialang.org/u/barucden)\
**Post date:** [February 3, 2026, 9:09am UTC](https://discourse.julialang.org/t/high-memory-usage-when-creating-lots-of-temporary-c-objects/135399/4 "2026-02-03T09:09:22Z")

</div>

Is this relevant: [Memory leak caused by inability to notify Julia GC about memory allocated by C++ · Issue #73 · JuliaInterop/libcxxwrap-julia · GitHub](https://github.com/JuliaInterop/libcxxwrap-julia/issues/73)?

---

<div class="post-metadata">

**Author:** ![Vasily\_Pisarev](https://sea2.discourse-cdn.com/julialang/user_avatar/discourse.julialang.org/vasily_pisarev/32/7929_2.png) [@Vasily\_Pisarev](https://discourse.julialang.org/u/Vasily_Pisarev)\
**Post date:** [February 3, 2026, 10:35am UTC](https://discourse.julialang.org/t/high-memory-usage-when-creating-lots-of-temporary-c-objects/135399/5 "2026-02-03T10:35:10Z")

</div>

Thanks!  
Yes, I think that’s the root issue.  
So, I guess the answer is no, I’m not missing any good recipe to deal with it?

---

<div class="post-metadata">

**Author:** ![Benny](https://avatars.discourse-cdn.com/v4/letter/b/49beb7/32.png) [@Benny](https://discourse.julialang.org/u/Benny)\
**Post date:** [February 3, 2026, 11:39am UTC](https://discourse.julialang.org/t/high-memory-usage-when-creating-lots-of-temporary-c-objects/135399/6 "2026-02-03T11:39:47Z")

</div>

> [@Vasily\_Pisarev](#):
>
> But the additional catch is that Julia runtime seems to be unaware of the C++ heap size and thus miscalculates when to run GC.

Tracking memory usage across language barriers is not trivial in general, and it’s extra important for tracing GCs triggered by memory pressure rather than variable lifetimes or reference counts. I don’t do my own language interop, but I’ve heard that `jl_malloc`/`jl_free` has been used to make Julia’s GC count C-allocated memory, and the `BigInt` implementation has apparently been [swapping out `libgmp`’s memory functions](https://github.com/JuliaLang/julia/blob/01a2eadb0474c395845e66ed3382b52e0c1f1b8f/base/gmp.jl#L117) e.g. `:jl_gc_counted_malloc`. No idea if or how this is generalized.

---

<div class="post-metadata">

**Author:** ![barche](https://sea2.discourse-cdn.com/julialang/user_avatar/discourse.julialang.org/barche/32/79_2.png) [@barche](https://discourse.julialang.org/u/barche)\
**Post date:** [February 3, 2026, 12:21pm UTC](https://discourse.julialang.org/t/high-memory-usage-when-creating-lots-of-temporary-c-objects/135399/7 "2026-02-03T12:21:57Z")

</div>

> [@Vasily\_Pisarev](#):
>
> On returning references: that might be helpful but I am not an expert. Would that need support from the wrapped C++ library to ensure correct memory management?

Assuming you are iterating over some large collection of objects that was already allocated in C++, then returning references instead of copies for each item should avoid this problem. I would need to see an example to know if this is possible here.

As seen in the linked issue, the general problem is indeed unsolved for now, the Julia GC has no idea how much memory is used by the wrapped C++ objects, and as far as I understand there is no functionality yet in the Julia API that we can use to inform it.

---

<div class="post-metadata">

**Author:** ![nsajko](https://sea2.discourse-cdn.com/julialang/user_avatar/discourse.julialang.org/nsajko/32/221187_2.png) [@nsajko](https://discourse.julialang.org/u/nsajko)\
**Post date:** [February 3, 2026, 12:24pm UTC](https://discourse.julialang.org/t/high-memory-usage-when-creating-lots-of-temporary-c-objects/135399/8 "2026-02-03T12:24:56Z")

</div>

> [@Vasily\_Pisarev](#):
>
> That rises an issue as each of the objects does not get immediately GC’ed if unused after the current iteration, so that memory allocation rises. Then at a later point GC `delete`s the objects. But the `delete` operator does not return the memory to the system but instead returns it to some memory pool for reuse. So, even though the objects get GC’ed at some point, the memory they allocated isn’t returned to the system.

A hack workaround is to run `GC.gc()` every so often. Or maybe even `GC.gc(); GC.gc()`, the second full collection tends to find some more garbage to collect.

After that, the allocated memory is still not necessarily returned to the operating system, depending on your platform/libc/allocator. For example, on Linux with Glibc, doing `GC.gc(); GC.gc(); @ccall malloc_trim(0::Cint)::Cvoid` might be able to free even more memory. The Julia developers are [considering](https://github.com/JuliaLang/julia/pull/60568) moving away from Glibc malloc for this, and other, reasons.

---

<div class="post-metadata">

**Author:** ![mattsignorelli](https://sea2.discourse-cdn.com/julialang/user_avatar/discourse.julialang.org/mattsignorelli/32/221502_2.png) [@mattsignorelli](https://discourse.julialang.org/u/mattsignorelli)\
**Post date:** [February 3, 2026, 1:16pm UTC](https://discourse.julialang.org/t/high-memory-usage-when-creating-lots-of-temporary-c-objects/135399/9 "2026-02-03T13:16:40Z")

</div>

I ran into the same problem with my package GTPSA.jl which wraps a C library.

> [@Benny](#):
>
> I don’t do my own language interop, but I’ve heard that `jl_malloc`/`jl_free` has been used to make Julia’s GC count C-allocated memory,

Yes, this has worked for me, and this is a viable solution for now.

You can allocate the memory directly in Julia itself. This requires using `ccall` and `jl_malloc`, as well as specifying `jl_free`. See my implementation here where we have a mutable Julia struct wrapping a C structure: [GTPSA.jl/src/tps.jl at 15f63c4f0ef1e2697197eb86a3cbd443ade259c4 · bmad-sim/GTPSA.jl · GitHub](https://github.com/bmad-sim/GTPSA.jl/blob/15f63c4f0ef1e2697197eb86a3cbd443ade259c4/src/tps.jl#L19-L53) . We allocate the arrays using `jl_malloc` and specify a finalizer with `jl_free`

---

<div class="post-metadata">

**Author:** ![Vasily\_Pisarev](https://sea2.discourse-cdn.com/julialang/user_avatar/discourse.julialang.org/vasily_pisarev/32/7929_2.png) [@Vasily\_Pisarev](https://discourse.julialang.org/u/Vasily_Pisarev)\
**Post date:** [February 3, 2026, 3:51pm UTC](https://discourse.julialang.org/t/high-memory-usage-when-creating-lots-of-temporary-c-objects/135399/10 "2026-02-03T15:51:45Z")

</div>

> [@barche](#):
>
> Assuming you are iterating over some large collection of objects that was already allocated in C++, then returning references instead of copies for each item should avoid this problem.

That’s the problem, the iteration is over a lazy collection, so that the objects are computed on the fly. The author’s intended approach was that user passes a preallocated buffer that gets mutated. I can make that the default iteration policy but then users would need to explicitly call `copy` whenever they want to decouple the curent object from the iteration state.  
Another option would indeed be to preallocate all cells on domain creation. That will have an upper bound on memory consumption, at least.

> [@nsajko](#):
>
> A hack workaround is to run `GC.gc()` every so often

Seems so. I guess the iteration state might need to include iteration counter to trigger GC at consistent intervals.

> [@nsajko](#):
>
> After that, the allocated memory is still not necessarily returned to the operating system, depending on your platform/libc/allocator.

That’s what I see. Calling `GC.gc()` stops memoy footprint from growing but does not release all the memory allocated for temporary objects.

> [@mattsignorelli](#):
>
> You can allocate the memory directly in Julia itself.

Not an option for me, I’m afraid, as the class under question does some dynamic memory management during object lifetime, so it’ll require rewriting the library internals. If not for that, it’d be the best solution (I guess, `jlcxx::create` does something of a kind, if not exactly that).
