# What am I doing wrong with \`unsafe\_wrap()\`?

**URL:** <https://discourse.julialang.org/t/what-am-i-doing-wrong-with-unsafe-wrap/75105>\
**Category:** General Usage\
**Created:** [January 24, 2022, 6:24am UTC](https://discourse.julialang.org/t/what-am-i-doing-wrong-with-unsafe-wrap/75105 "2022-01-24T06:24:50Z")\
**Posts on this page:** 11\
**Page:** 1

<div class="post-metadata">

**Author:** ![heyx3](https://sea2.discourse-cdn.com/julialang/user_avatar/discourse.julialang.org/heyx3/32/29811_2.png) [@heyx3](https://discourse.julialang.org/u/heyx3)\
**Post date:** [January 24, 2022, 6:24am UTC](https://discourse.julialang.org/t/what-am-i-doing-wrong-with-unsafe-wrap/75105/1 "2022-01-24T06:24:50Z")

</div>

Trying to write some test code with `unsafe_wrap()`, and getting unexpected garbage results.

```julia
julia> function f()
          r = Ref(tuple(5.0, 2.0, 1.0, 6.0))
          p = Base.unsafe_convert(Ptr{Float64}, r)
          u = unsafe_wrap(Array, p, 4)
          display(u)
          return nothing
       end
f (generic function with 1 method)

julia> f()
4-element Vector{Float64}:
 1.20926195e-315
 6.341044e-317
 1.4669e-319
 2.12443504e-316

```

Why is it not printing an array of `[5.0, 2.0, 1.0, 6.0]`?

---

<div class="post-metadata">

**Author:** ![simeonschaub](https://sea2.discourse-cdn.com/julialang/user_avatar/discourse.julialang.org/simeonschaub/32/216566_2.png) [@simeonschaub](https://discourse.julialang.org/u/simeonschaub)\
**Post date:** [January 24, 2022, 7:04am UTC](https://discourse.julialang.org/t/what-am-i-doing-wrong-with-unsafe-wrap/75105/2 "2022-01-24T07:04:22Z")

</div>

You didn’t root `r` here, so it likely got garbage collected before the `display` call. You need to wrap all code which references `r` by pointer with `GC.@preserve`:

```julia
julia> function f()
          r = Ref(tuple(5.0, 2.0, 1.0, 6.0))
          GC.@preserve r begin
              p = Base.unsafe_convert(Ptr{Float64}, r)
              u = unsafe_wrap(Array, p, 4)
              display(u)
          end
          return nothing
       end
f (generic function with 1 method)

julia> f()
4-element Vector{Float64}:
 5.0
 2.0
 1.0
 6.0

```

Also note that you can’t leak `u` from this function without also ensuring `r` is rooted somehow. I’d recommend checking out the ffi section of the manual:

[https://docs.julialang.org/en/v1/manual/calling-c-and-fortran-code/](https://docs.julialang.org/en/v1/manual/calling-c-and-fortran-code/)

---

<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:** [January 24, 2022, 7:06am UTC](https://discourse.julialang.org/t/what-am-i-doing-wrong-with-unsafe-wrap/75105/3 "2022-01-24T07:06:37Z")

</div>

Similarly, you could just return `r`.

```julia
julia> function f()
                 r = Ref(tuple(5.0, 2.0, 1.0, 6.0))
                 p = Base.unsafe_convert(Ptr{Float64}, r)
                 u = unsafe_wrap(Array, p, 4)
                 display(u)
                 return r
              end

julia> f();
4-element Vector{Float64}:
 5.0
 2.0
 1.0
 6.0

```

---

<div class="post-metadata">

**Author:** ![simeonschaub](https://sea2.discourse-cdn.com/julialang/user_avatar/discourse.julialang.org/simeonschaub/32/216566_2.png) [@simeonschaub](https://discourse.julialang.org/u/simeonschaub)\
**Post date:** [January 24, 2022, 7:16am UTC](https://discourse.julialang.org/t/what-am-i-doing-wrong-with-unsafe-wrap/75105/4 "2022-01-24T07:16:25Z")

</div>

It’s still recommended to use `GC.@preserve` here. With further compiler optimizations in the very near future, these kinds of allocations could still be eliminated if `r` doesn’t escape from the caller, for example if `f` is called from another function.

---

<div class="post-metadata">

**Author:** ![jling](https://sea2.discourse-cdn.com/julialang/user_avatar/discourse.julialang.org/jling/32/212909_2.png) [@jling](https://discourse.julialang.org/u/jling)\
**Post date:** [January 24, 2022, 7:30am UTC](https://discourse.julialang.org/t/what-am-i-doing-wrong-with-unsafe-wrap/75105/5 "2022-01-24T07:30:47Z")

</div>

I don’t think it works even with `@preserve`, outside of the function, Julia doesn’t know it needs to preserve `r` in order to keep `u`, because `u` doesn’t contain reference to `r` anymore.

you need to finish dealing with both `u` and `r` within the same `@preserve` block, which means you can’t return `u` and expect the underlying content to stay around.

* * *

other-wise we wouldn’t have struggled with: [https://github.com/JuliaLang/julia/issues/42227](https://github.com/JuliaLang/julia/issues/42227)

---

<div class="post-metadata">

**Author:** ![jling](https://sea2.discourse-cdn.com/julialang/user_avatar/discourse.julialang.org/jling/32/212909_2.png) [@jling](https://discourse.julialang.org/u/jling)\
**Post date:** [January 24, 2022, 7:35am UTC](https://discourse.julialang.org/t/what-am-i-doing-wrong-with-unsafe-wrap/75105/6 "2022-01-24T07:35:26Z")

</div>

side comment: unfortunately this is one of very rare occasion where the task is so trivial in C/C++ (“just unsafe cast the pointer trust me”), and impossible to do in Julia because we can’t manually mark/unmark new root object for GC.

Essentially it’s impossible to write a function:

```julia
f(T, arr::Vector{W}) where {T,W}

```

that takes an `arr`, “unsafe wrap” it into a `Vector` of different type, and return a built-in, clean `Vector{T}`.

You need to make something like a:

```julia
struct MyVector{T, W}
newarr::Vector{T}
ref::Ref{Vector{W}}
end

```

* * *

now, I just realized in this case, OP has a `Ref{Tuple}`, maybe that makes things different because Tuple is immutable, but it seems like GC still cares

---

<div class="post-metadata">

**Author:** ![tkf](https://sea2.discourse-cdn.com/julialang/user_avatar/discourse.julialang.org/tkf/32/17635_2.png) [@tkf](https://discourse.julialang.org/u/tkf)\
**Post date:** [January 24, 2022, 7:43am UTC](https://discourse.julialang.org/t/what-am-i-doing-wrong-with-unsafe-wrap/75105/7 "2022-01-24T07:43:29Z")

</div>

`GC.@preserve` is required. Consider

```julia
function g()
    f()
    nothing
end

```

When `f` is inlined, `r` is not returned anymore and Julia and LLVM are not required to preserve `r`.

Besides, unless `own = true` is passed, the programmer is responsible for keeping the memory behind the pointer `p` alive. `GC.@preserve` is virtually the only way to do it if the memory region is allocated as a Julia object. But I think most of the confusion is coming from the lack of documentation. We need to have better documentation on what is allowed (which may actually need to start from discussing what should be allowed).

(There’s also a question that if this kind of type-punning is actually OK to do. The compiler can, in principle, start using Julia-level type information more aggressively to reason about aliasing.)

It may be straightforward to do type-punning in C but I wouldn’t say it’s trivial to do in C++ when you have various hours-long talks on how to do it properly in C++ (e.g., [Type punning in modern C++ - Timur Doumler - CppCon 2019 - YouTube](https://www.youtube.com/watch?v=_qzMpk-22cc)). Like C++, Julia needs to provide some constructs for doing this in a type system-compatible manner. C++ got [`std::bit_cast`](https://en.cppreference.com/w/cpp/numeric/bit_cast) only in C++20 so it’s not like we are very behind. ReinterpretArray essentially does what C++ does but there’s no public API for doing this properly.

---

<div class="post-metadata">

**Author:** ![jling](https://sea2.discourse-cdn.com/julialang/user_avatar/discourse.julialang.org/jling/32/212909_2.png) [@jling](https://discourse.julialang.org/u/jling)\
**Post date:** [January 24, 2022, 7:45am UTC](https://discourse.julialang.org/t/what-am-i-doing-wrong-with-unsafe-wrap/75105/8 "2022-01-24T07:45:54Z")

</div>

I would think at least for “plain” “isbittype” vector, it’s trivial to cast with the same set of underlying bytes in C or C++, which is really the most useful case because it’s probably some kind of I/O or binary data format processing task

---

<div class="post-metadata">

**Author:** ![c42f](https://sea2.discourse-cdn.com/julialang/user_avatar/discourse.julialang.org/c42f/32/52842_2.png) [@c42f](https://discourse.julialang.org/u/c42f)\
**Post date:** [January 24, 2022, 7:54am UTC](https://discourse.julialang.org/t/what-am-i-doing-wrong-with-unsafe-wrap/75105/9 "2022-01-24T07:54:54Z")

</div>

> [@jling](#):
>
> Essentially it’s impossible to write a function:
> 
> ```julia
> f(T, arr::Vector{W}) where {T,W}
> 
> ```
> 
> that takes an `arr` , “unsafe wrap” it into a `Vector` of different type, and return a built-in, clean `Vector{T}` .

It’s true that if you stray outside Julia’s model of ownership things do get messy and manual.

With [`ResourceContexts.jl`](https://github.com/c42f/ResourceContexts.jl) I tried to tackle some of these problems. For example we have the following entertaining example of returning a bare `Ptr` to a temporary buffer, at the cost of using the `@!` macro:

```julia
@! function raw_buffer(len)
    buf = Vector{UInt8}(undef, len)
    @defer GC.@preserve buf nothing
    pointer(buf)
end

@context begin
    len = 1_000_000_000
    ptr = @! raw_buffer(len)
    GC.gc() # `buf` is preserved regardless of this call to gc()
    unsafe_store!(ptr, 0xff)
end

```

Those macros are ugly to be sure! I hope one day we can have some more official and builtin variant of this (or other equivalent) kind of thing which works with the language’s natural scoping rules.

---

<div class="post-metadata">

**Author:** ![c42f](https://sea2.discourse-cdn.com/julialang/user_avatar/discourse.julialang.org/c42f/32/52842_2.png) [@c42f](https://discourse.julialang.org/u/c42f)\
**Post date:** [January 24, 2022, 8:01am UTC](https://discourse.julialang.org/t/what-am-i-doing-wrong-with-unsafe-wrap/75105/10 "2022-01-24T08:01:08Z")

</div>

> [@jling](#):
>
> I would think at least for “plain” “isbittype” vector, it’s trivial to cast with the same set of underlying bytes in C or C++, which is really the most useful case because it’s probably some kind of I/O or binary data format processing task

It’s not really that simple. Type punning violates the C++ strict aliasing rules, and compilers will be happy to interpret your code in a way you didn’t intend. See for example [c++ - What is the strict aliasing rule? - Stack Overflow](https://stackoverflow.com/questions/98650/what-is-the-strict-aliasing-rule)

---

<div class="post-metadata">

**Author:** ![tkf](https://sea2.discourse-cdn.com/julialang/user_avatar/discourse.julialang.org/tkf/32/17635_2.png) [@tkf](https://discourse.julialang.org/u/tkf)\
**Post date:** [January 24, 2022, 8:38am UTC](https://discourse.julialang.org/t/what-am-i-doing-wrong-with-unsafe-wrap/75105/11 "2022-01-24T08:38:16Z")

</div>

Casting between different pointer types in general are UB, even in C, IIUC. But you can always cast _to_ bytes (`char*`). So, the basic strategy to reinterpret `T` to `S` is to cast their pointers as pointers to bytes, memcpy the bytes, and load `S`. I’d imagine this is why `std::bit_cast` returns a value and not a reference (to help TBAA). That’s the strategy I followed in [https://github.com/JuliaLang/julia/pull/43065](https://github.com/JuliaLang/julia/pull/43065)
