# \`unsafe\_wrap\` on memory created by \`:jl\_malloc\`

**URL:** https://discourse.julialang.org/t/unsafe-wrap-on-memory-created-by-jl-malloc/66826
**Category:** Internals & Design
**Tags:** question
**Created:** [August 23, 2021, 3:23am UTC](https://discourse.julialang.org/t/unsafe-wrap-on-memory-created-by-jl-malloc/66826 "2021-08-23T03:23:03Z")
**Posts on this page:** 6
**Page:** 1

<div class="post-metadata">

### Author: ![rayegun](https://sea2.discourse-cdn.com/julialang/user_avatar/discourse.julialang.org/rayegun/32/26729_2.png) [@rayegun](https://discourse.julialang.org/u/rayegun)
#### Post date: [August 23, 2021, 3:23am UTC](https://discourse.julialang.org/t/unsafe-wrap-on-memory-created-by-jl-malloc/66826/1 "2021-08-23T03:23:03Z")

</div>

I’m probably diving too deep trying to make things fast (again) but I was hoping there was a way to make this work. Sorry to bother, I’ve asked a lot of questions about memory management stuff recently.

I have a C library that can take ownership of memory and return it (SuiteSparse:GraphBLAS). I give the library the `:jl_malloc` and friends functions at init time.

Currently to give the C library a vector for instance I need to do an `unsafe_copyto!` to memory created by `:jl_malloc`. That’s fine, although it’s slower and limits my arrays to \<\< 1/2 of memory since there’s a copy.

Up until today I did the same in reverse, by doing something like `v = Vector{T}(undef, n)` and `unsafe_copyto!(pointer(v), Ptr{T}(ptrtocarray[]), length(v))`.

I’d really like to use `unsafe_wrap` to do this. Unfortunately I’m doing something wrong with the combination of `unsafe_wrap` and `:jl_malloc`. See MWE here:

MWE:

```julia
               _
   _ _ _(_)_ | Documentation: https://docs.julialang.org
  (_) | (_) (_) |
   _ _ _| |_ __ _ | Type "?" for help, "]?" for Pkg help.
  | | | | | | |/ _` | |
  | | |_| | | | (_| | | Version 1.6.2 (2021-07-14)
 _/ |\ __'_|_|_|\__'_| | Official https://julialang.org/ release
|__/ |

julia> x = [1,2,3]
3-element Vector{Int64}:
 1
 2
 3

julia> z = ccall(:jl_malloc, Ptr{Int64}, (Int64, ), 3)
Ptr{Int64} @0x00000000026a1e30

julia> unsafe_copyto!(z, pointer(x), length(x))
Ptr{Int64} @0x00000000026a1e30

julia> z2 = unsafe_wrap(Array, z, 3; own = true)
3-element Vector{Int64}:
 1
 2
 3

julia> z2 = nothing

julia> GC.gc()
free(): invalid pointer

signal (6): Aborted
in expression starting at REPL[7]:1
gsignal at /lib/x86_64-linux-gnu/libc.so.6 (unknown line)
abort at /lib/x86_64-linux-gnu/libc.so.6 (unknown line)
unknown function (ip: 0x7f7edc8fe507)
unknown function (ip: 0x7f7edc904c19)
unknown function (ip: 0x7f7edc90642b)
jl_gc_free_array at /buildworker/worker/package_linux64/build/src/gc.c:1111 [inlined]
sweep_malloced_arrays at /buildworker/worker/package_linux64/build/src/gc.c:1132 [inlined]
gc_sweep_other at /buildworker/worker/package_linux64/build/src/gc.c:1467 [inlined]
_jl_gc_collect at /buildworker/worker/package_linux64/build/src/gc.c:3144
jl_gc_collect at /buildworker/worker/package_linux64/build/src/gc.c:3240
gc at ./gcutils.jl:94 [inlined]
gc at ./gcutils.jl:94
unknown function (ip: 0x7f7e82a806dc)
_jl_invoke at /buildworker/worker/package_linux64/build/src/gf.c:2237 [inlined]
jl_apply_generic at /buildworker/worker/package_linux64/build/src/gf.c:2419
jl_apply at /buildworker/worker/package_linux64/build/src/julia.h:1703 [inlined]
do_call at /buildworker/worker/package_linux64/build/src/interpreter.c:115
eval_value at /buildworker/worker/package_linux64/build/src/interpreter.c:204
eval_stmt_value at /buildworker/worker/package_linux64/build/src/interpreter.c:155 [inlined]
eval_body at /buildworker/worker/package_linux64/build/src/interpreter.c:562
jl_interpret_toplevel_thunk at /buildworker/worker/package_linux64/build/src/interpreter.c:670
jl_toplevel_eval_flex at /buildworker/worker/package_linux64/build/src/toplevel.c:877
jl_toplevel_eval_flex at /buildworker/worker/package_linux64/build/src/toplevel.c:825
jl_toplevel_eval_flex at /buildworker/worker/package_linux64/build/src/toplevel.c:825
jl_toplevel_eval_in at /buildworker/worker/package_linux64/build/src/toplevel.c:929
eval at ./boot.jl:360 [inlined]
eval_user_input at /buildworker/worker/package_linux64/build/usr/share/julia/stdlib/v1.6/REPL/src/REPL.jl:139
repl_backend_loop at /buildworker/worker/package_linux64/build/usr/share/julia/stdlib/v1.6/REPL/src/REPL.jl:200
start_repl_backend at /buildworker/worker/package_linux64/build/usr/share/julia/stdlib/v1.6/REPL/src/REPL.jl:185
#run_repl#42 at /buildworker/worker/package_linux64/build/usr/share/julia/stdlib/v1.6/REPL/src/REPL.jl:317
run_repl at /buildworker/worker/package_linux64/build/usr/share/julia/stdlib/v1.6/REPL/src/REPL.jl:305
_jl_invoke at /buildworker/worker/package_linux64/build/src/gf.c:2237 [inlined]
jl_apply_generic at /buildworker/worker/package_linux64/build/src/gf.c:2419
#874 at ./client.jl:387
jfptr_YY.874_23032.clone_1 at /home/will/julia-1.6.2/lib/julia/sys.so (unknown line)
_jl_invoke at /buildworker/worker/package_linux64/build/src/gf.c:2237 [inlined]
jl_apply_generic at /buildworker/worker/package_linux64/build/src/gf.c:2419
jl_apply at /buildworker/worker/package_linux64/build/src/julia.h:1703 [inlined]
jl_f__call_latest at /buildworker/worker/package_linux64/build/src/builtins.c:714
#invokelatest#2 at ./essentials.jl:708 [inlined]
invokelatest at ./essentials.jl:706 [inlined]
run_main_repl at ./client.jl:372
exec_options at ./client.jl:302
_start at ./client.jl:485
jfptr__start_34281.clone_1 at /home/will/julia-1.6.2/lib/julia/sys.so (unknown line)
_jl_invoke at /buildworker/worker/package_linux64/build/src/gf.c:2237 [inlined]
jl_apply_generic at /buildworker/worker/package_linux64/build/src/gf.c:2419
jl_apply at /buildworker/worker/package_linux64/build/src/julia.h:1703 [inlined]
true_main at /buildworker/worker/package_linux64/build/src/jlapi.c:560
repl_entrypoint at /buildworker/worker/package_linux64/build/src/jlapi.c:702
main at julia (unknown line)
__libc_start_main at /lib/x86_64-linux-gnu/libc.so.6 (unknown line)
unknown function (ip: 0x4007d8)
Allocations: 4258497 (Pool: 4256858; Big: 1639); GC: 5
Aborted

```

Perhaps `unsafe_wrap` is the wrong function for the job since the garbage collector is _already_ technically aware of this memory, and I’m somehow confusing it (more likely is that it’s smarter than me)?

~~There’s another option to `unsafe_wrap` with `own=false` and then register a finalizer that calls `:jl_free`. Is that what I should do?~~ I don’t think this really works.

---

<div class="post-metadata">

### Author: ![DatName](https://sea2.discourse-cdn.com/julialang/user_avatar/discourse.julialang.org/datname/32/418_2.png) [@DatName](https://discourse.julialang.org/u/DatName)
#### Post date: [October 2, 2021, 4:30am UTC](https://discourse.julialang.org/t/unsafe-wrap-on-memory-created-by-jl-malloc/66826/2 "2021-10-02T04:30:17Z")

</div>

> [@rayegun](#):
>
> `z = ccall(:jl_malloc, Ptr{Int64}, (Int64, ), 3)`

Seems like you’ve allocated 3 bytes for your 24-byte array. Try

```julia
z = ccall(:jl_malloc, Ptr{Cvoid}, (UInt64, ), sizeof(x))

```

instead.

---

<div class="post-metadata">

### Author: ![rayegun](https://sea2.discourse-cdn.com/julialang/user_avatar/discourse.julialang.org/rayegun/32/26729_2.png) [@rayegun](https://discourse.julialang.org/u/rayegun)
#### Post date: [October 7, 2021, 7:40pm UTC](https://discourse.julialang.org/t/unsafe-wrap-on-memory-created-by-jl-malloc/66826/3 "2021-10-07T19:40:59Z")

</div>

I still get a segfault on `GC.gc()` replacing that line? Do you?

---

<div class="post-metadata">

### Author: ![DatName](https://sea2.discourse-cdn.com/julialang/user_avatar/discourse.julialang.org/datname/32/418_2.png) [@DatName](https://discourse.julialang.org/u/DatName)
#### Post date: [October 11, 2021, 3:00am UTC](https://discourse.julialang.org/t/unsafe-wrap-on-memory-created-by-jl-malloc/66826/4 "2021-10-11T03:00:04Z")

</div>

Hm, I dont:

```julia
               _
   _ _ _(_)_ | Documentation: https://docs.julialang.org
  (_) | (_) (_) |
   _ _ _| |_ __ _ | Type "?" for help, "]?" for Pkg help.
  | | | | | | |/ _` | |
  | | |_| | | | (_| | | Version 1.6.2 (2021-07-14)
 _/ |\ __'_|_|_|\__'_| | Official https://julialang.org/ release
|__/ |

julia> x = [1,2,3]
3-element Vector{Int64}:
 1
 2
 3

julia> z = ccall(:jl_malloc, Ptr{Int64}, (UInt64, ), sizeof(x))
Ptr{Int64} @0x00000000026c1320

julia> unsafe_copyto!(z, pointer(x), 3)
Ptr{Int64} @0x00000000026c1320

julia> z2 = unsafe_wrap(Array, z, 3; own = true)
3-element Vector{Int64}:
 1
 2
 3

julia> GC.gc()

julia> 

```

---

<div class="post-metadata">

### Author: ![rayegun](https://sea2.discourse-cdn.com/julialang/user_avatar/discourse.julialang.org/rayegun/32/26729_2.png) [@rayegun](https://discourse.julialang.org/u/rayegun)
#### Post date: [October 11, 2021, 4:32am UTC](https://discourse.julialang.org/t/unsafe-wrap-on-memory-created-by-jl-malloc/66826/5 "2021-10-11T04:32:11Z")

</div>

Need to do `z2 = nothing`. You’re not GCing anything (AFAIK)

---

<div class="post-metadata">

### Author: ![thofma](https://sea2.discourse-cdn.com/julialang/user_avatar/discourse.julialang.org/thofma/32/1691_2.png) [@thofma](https://discourse.julialang.org/u/thofma)
#### Post date: [November 10, 2021, 1:31pm UTC](https://discourse.julialang.org/t/unsafe-wrap-on-memory-created-by-jl-malloc/66826/6 "2021-11-10T13:31:34Z")

</div>

The docstring of `unsafe_wrap` says that it calls `free` for `own = true`. But `free` cannot directly be used on `jl_malloc`’ed memory. Either `free` on `malloc`’ed or `jl_free` on `jl_malloced`’ed memory. At least this is my understanding.
