Is this conversion+store safe?

I’m wondering if this is a correct usage of these unsafe functions:

julia> using StaticArrays

julia> a = MVector{4,UInt}(1,2,3,4);

julia> b = UInt.((5,6,7,8));

julia> function f(a, b)
           dst = Base.unsafe_convert(Ptr{MVector{4, UInt64}}, a)
           unsafe_store!(dst, b)
           return a
       end

julia> f(a, b)
4-element MVector{4, UInt64} with indices SOneTo(4):
 0x0000000000000005
 0x0000000000000006
 0x0000000000000007
 0x0000000000000008

is it?

Should I use instead

julia> function f(a, b)
           GC.@preserve a begin
               dst = Base.unsafe_convert(Ptr{MVector{4, UInt64}}, a)
               unsafe_store!(dst, b)
           end
           return a
       end

maybe?

Since this is an MVector, why use unsafe functions at all?

2 Likes

No, it’ll crash

Certainly better, although these things can be very tricky and I don’t think we’re guaranteeing the memory layout here. If at all possible, try to use the APIs provided by the package (which may do similar things, but will likely get caught in PkgEval if we break an implicit assumption). If the issue is performance, file an issue.

3 Likes

To expand on this, you can just use a.data = b here:

julia> using StaticArrays

julia> a = MVector{4, UInt}(1,2,3,4);

julia> b = UInt.((5,6,7,8));

julia> a.data = b;

julia> a
4-element MVector{4, UInt64} with indices SOneTo(4):
 0x0000000000000005
 0x0000000000000006
 0x0000000000000007
 0x0000000000000008

If you’re exploring unsafe pointer shenanigans though, it’s perhaps also worth noting if you’re going down this path that you can’t unsafe_load a Ptr{T} when T is a mutable type (like MVector), since the GC will incorrectly reason about the loaded object.

2 Likes

thank you all! Indeed, I can use the straightforward version of @Mason, I thought the only other option was a[1]=b[1], a[2]=b[2], ...

1 Like