# Memory management and PackageCompiler libraries

**URL:** <https://discourse.julialang.org/t/memory-management-and-packagecompiler-libraries/72980>\
**Category:** General Usage\
**Tags:** embedding, memory, package-compiler\
**Created:** [December 12, 2021, 3:12pm UTC](https://discourse.julialang.org/t/memory-management-and-packagecompiler-libraries/72980 "2021-12-12T15:12:15Z")\
**Posts on this page:** 9\
**Page:** 1

<div class="post-metadata">

**Author:** ![originalsouth](https://sea2.discourse-cdn.com/julialang/user_avatar/discourse.julialang.org/originalsouth/32/32061_2.png) [@originalsouth](https://discourse.julialang.org/u/originalsouth)\
**Post date:** [December 12, 2021, 3:12pm UTC](https://discourse.julialang.org/t/memory-management-and-packagecompiler-libraries/72980/1 "2021-12-12T15:12:15Z")

</div>

Hello,

I have a question regarding memory management when retrieving arbitrary sized memory blocks from a library compiled by the PackageCompiler.

In [https://github.com/originalsouth/RandomPack](https://github.com/originalsouth/RandomPack) I have created a dummy project where the file `src/RandomPack.jl` returns arbitrary sized Cstrings.

After running `make -C build` the C program with its source in `build/RandomPack.c` retrieves a bunch of Cstrings from the compiled Julia implementation and prints them – which works 😃

My questions, however, what is the lifetime of the memory allocated for the strings generated in `const char *random_pack(const char *str)`, what part of the code ought to be responsible for the memory management, and how can I control (not) freeing the memory up?

Things I have played with:

- Calling `void free(void *ptr)` from the C-code which crashes the Julia library
- Calling `GC.gc()` after every Julia side function call (this makes the code slow and invalidates the pointers indeed)

Thanks a lot in advance,  
Cheers!

---

<div class="post-metadata">

**Author:** ![kristoffer.carlsson](https://sea2.discourse-cdn.com/julialang/user_avatar/discourse.julialang.org/kristoffer.carlsson/32/22_2.png) [@kristoffer.carlsson](https://discourse.julialang.org/u/kristoffer.carlsson)\
**Post date:** [December 12, 2021, 3:37pm UTC](https://discourse.julialang.org/t/memory-management-and-packagecompiler-libraries/72980/2 "2021-12-12T15:37:50Z")

</div>

> [@originalsouth](#):
>
> how can I control (not) freeing the memory up?

You can “root” the object by storing it in a global array for example. Then the Julia GC will not clean it up.

---

<div class="post-metadata">

**Author:** ![anon56330260](https://avatars.discourse-cdn.com/v4/letter/a/f07891/32.png) [@anon56330260](https://discourse.julialang.org/u/anon56330260)\
**Post date:** [December 12, 2021, 4:26pm UTC](https://discourse.julialang.org/t/memory-management-and-packagecompiler-libraries/72980/3 "2021-12-12T16:26:19Z")

</div>

I would recommend you copy the string. So in your Julia code, you manually allocate a unmanaged memory and copy the content to this memory area, then you free this memory in your C code after usage. The pseudo code looks like this:

```julia
Base.@ccallable function random_pack(input::Cstring)::Cstring
    jinput = unsafe_string(input)
    str = randstring(rand(length(jinput):rand(2:12)*length(jinput)))
    finalstr = jinput * ":" * str
    ptr = Base.Libc.malloc(sizeof(finalstr))
    # maybe gc preserve is needed here, we copy the content to ptr
    memcpy(ptr, finalstr)
    return Base.Cstring(ptr)
end

```

---

<div class="post-metadata">

**Author:** ![originalsouth](https://sea2.discourse-cdn.com/julialang/user_avatar/discourse.julialang.org/originalsouth/32/32061_2.png) [@originalsouth](https://discourse.julialang.org/u/originalsouth)\
**Post date:** [December 13, 2021, 11:37am UTC](https://discourse.julialang.org/t/memory-management-and-packagecompiler-libraries/72980/4 "2021-12-13T11:37:32Z")

</div>

Thanks! A global Set as “root” with a release call, _feels_ wrong but I guess that is the way to go 🙂

Edit: There seems to a similar solution here…

> [@How to keep a reference for C structure to avoid GC?](https://discourse.julialang.org/t/how-to-keep-a-reference-for-c-structure-to-avoid-gc/9310/3):
>
> Don’t use a global dict, that’s not generic and is the slowest possible solution. What you can use depends on how you are calling the C code. A possible solution that should work in most cases is [https://github.com/JuliaPy/PyCall.jl/blob/314ac274326e78f12fbcb73ae0f17f63a3f4bba9/src/pytype.jl#L314](https://github.com/JuliaPy/PyCall.jl/blob/314ac274326e78f12fbcb73ae0f17f63a3f4bba9/src/pytype.jl#L314)

---

<div class="post-metadata">

**Author:** ![originalsouth](https://sea2.discourse-cdn.com/julialang/user_avatar/discourse.julialang.org/originalsouth/32/32061_2.png) [@originalsouth](https://discourse.julialang.org/u/originalsouth)\
**Post date:** [December 13, 2021, 11:39am UTC](https://discourse.julialang.org/t/memory-management-and-packagecompiler-libraries/72980/5 "2021-12-13T11:39:41Z")

</div>

I like this idea, especially when working with small objects.

I tried implementing it but it somehow still leaks when valgrinding…

```julia
Base.@ccallable function random_pack(input::Cstring)::Cstring
    jinput = unsafe_string(input)
    str = randstring(rand(length(jinput):rand(2:12)*length(jinput)))
    retval = jinput * ":" * str
    ptr = Base.convert(Ptr{UInt8}, Base.Libc.malloc(1 + length(retval)))
    Base.unsafe_copyto!(ptr, pointer(Base.cconvert(Cstring, retval)), 1 + length(retval))
    return Base.Cstring(ptr)
end

```

Probably, I am still doing something wrong.

---

<div class="post-metadata">

**Author:** ![anon56330260](https://avatars.discourse-cdn.com/v4/letter/a/f07891/32.png) [@anon56330260](https://discourse.julialang.org/u/anon56330260)\
**Post date:** [December 16, 2021, 3:26am UTC](https://discourse.julialang.org/t/memory-management-and-packagecompiler-libraries/72980/6 "2021-12-16T03:26:05Z")

</div>

Sorry for the late reply. I think you need to preserve `retval` getting gc by using `Base.GC.@preserve`. Here is the complete code.

```julia
function string_copy(s::String)
    # we copy codeunit here
    nc = ncodeunits(s)
    # 1 for '\0', I am not sure whether Julia's string is zero terminated, so I just add my own one
    ptr = Base.unsafe_convert(Ptr{UInt8}, Base.Libc.malloc(nc + 1))
    Base.unsafe_store!(ptr, UInt8('\0'), nc + 1)
    # we mark the string as in use, to prevent pointer getting gc
    Base.GC.@preserve s begin
        str_ptr = Base.unsafe_convert(Ptr{UInt8}, s)
        Base.unsafe_copyto!(ptr, str_ptr, nc)
    end
    return Base.Cstring(ptr)
end

```

Test code:

```julia
let
    x = "1,2,3"
    c_str = string_copy(x)
    Base.unsafe_string(c_str) == x
    Base.Libc.free(c_str)
end

```

---

<div class="post-metadata">

**Author:** ![originalsouth](https://sea2.discourse-cdn.com/julialang/user_avatar/discourse.julialang.org/originalsouth/32/32061_2.png) [@originalsouth](https://discourse.julialang.org/u/originalsouth)\
**Post date:** [December 16, 2021, 8:44am UTC](https://discourse.julialang.org/t/memory-management-and-packagecompiler-libraries/72980/7 "2021-12-16T08:44:52Z")

</div>

Thank you for you reply!

Ah, right the terminating zero might have caused the missed reads, in some cases – let me test.

Yet, I am a little confused still with the preserve.  
I think the memory allocated by `malloc` is outside of the `GC` and thus needs to be freed whenever we are done. The pointer itself (i.e. the memory address of the allocated memory), however, can and should be deleted by the `GC` once we have handed it over to the C-side. Are we therefore not causing a memory leak preserving the pointer?

---

<div class="post-metadata">

**Author:** ![anon56330260](https://avatars.discourse-cdn.com/v4/letter/a/f07891/32.png) [@anon56330260](https://discourse.julialang.org/u/anon56330260)\
**Post date:** [December 16, 2021, 10:13am UTC](https://discourse.julialang.org/t/memory-management-and-packagecompiler-libraries/72980/8 "2021-12-16T10:13:11Z")

</div>

We have two pointers here: the pointer allocated by `malloc` and the underlying pointer of `String`. The latter is managed by GC. We need to ensure this pointer is valid (not gc by Julia) when we copy the content of this pointer to the manually allocated one. That’s why we need to preserve the string (we do not preserve the manually allocated pointer). Also, `GC.@preserve` only take effects locally. For example:

```julia
Base.GC.@preserve s begin
  str_ptr = Base.unsafe_convert(Ptr{UInt8}, s)
  Base.unsafe_copyto!(ptr, str_ptr, nc)
end

```

After the evaluation of `begin` block, `s` is not preserved (s is only preserved during the evaluation of the block`).

---

<div class="post-metadata">

**Author:** ![originalsouth](https://sea2.discourse-cdn.com/julialang/user_avatar/discourse.julialang.org/originalsouth/32/32061_2.png) [@originalsouth](https://discourse.julialang.org/u/originalsouth)\
**Post date:** [December 16, 2021, 10:37am UTC](https://discourse.julialang.org/t/memory-management-and-packagecompiler-libraries/72980/9 "2021-12-16T10:37:33Z")

</div>

Thanks! It all makes sense now 😃
