• Home
  • Features
  • Pricing
  • Docs
  • Announcements
  • Sign In

JuliaLang / julia / 1257

01 Sep 2025 06:55PM UTC coverage: 76.743% (+2.0%) from 74.77%
1257

push

buildkite

web-flow
Bump actions/checkout from 4.2.2 to 5.0.0 (#59453)

61036 of 79533 relevant lines covered (76.74%)

23153196.42 hits per line

Source File
Press 'n' to go to next uncovered line, 'b' for previous

87.67
/base/pointer.jl
1
# This file is a part of Julia. License is MIT: https://julialang.org/license
2

3
"""
4
    Ptr{T}
5

6
A memory address referring to data of type `T`.  However, there is no guarantee that the
7
memory is actually valid, or that it actually represents data of the specified type.
8
"""
9
Ptr
10

11
## converting pointers to an appropriate unsigned ##
12

13
"""
14
    C_NULL
15

16
The C null pointer constant, sometimes used when calling external code.
17
"""
18
const C_NULL = bitcast(Ptr{Cvoid}, 0)
19

20
# TODO: deprecate these conversions. C doesn't even allow them.
21

22
# pointer to integer
23
convert(::Type{T}, x::Ptr) where {T<:Integer} = T(UInt(x))::T
6,024✔
24

25
# integer to pointer
26
convert(::Type{Ptr{T}}, x::Union{Int,UInt}) where {T} = Ptr{T}(x)
27,825✔
27

28
# pointer to pointer
29
convert(::Type{Ptr{T}}, p::Ptr{T}) where {T} = p
193,501,046✔
30
convert(::Type{Ptr{T}}, p::Ptr) where {T} = bitcast(Ptr{T}, p)::Ptr{T}
2,378,808,298✔
31

32
# object to pointer (when used with ccall)
33

34
"""
35
    unsafe_convert(T, x)
36

37
Convert `x` to a C argument of type `T`
38
where the input `x` must be the return value of `cconvert(T, ...)`.
39

40
In cases where [`convert`](@ref) would need to take a Julia object
41
and turn it into a `Ptr`, this function should be used to define and perform
42
that conversion.
43

44
Be careful to ensure that a Julia reference to `x` exists as long as the result of this
45
function will be used. Accordingly, the argument `x` to this function should never be an
46
expression, only a variable name or field reference. For example, `x=a.b.c` is acceptable,
47
but `x=[a,b,c]` is not.
48

49
The `unsafe` prefix on this function indicates that using the result of this function after
50
the `x` argument to this function is no longer accessible to the program may cause undefined
51
behavior, including program corruption or segfaults, at any later time.
52

53
See also [`cconvert`](@ref)
54
"""
55
function unsafe_convert end
56

57
# convert strings to String etc. to pass as pointers
58
cconvert(::Type{Ptr{UInt8}}, s::AbstractString) = String(s)
7,007,768✔
59
cconvert(::Type{Ptr{Int8}}, s::AbstractString) = String(s)
4✔
60
unsafe_convert(::Type{Ptr{UInt8}}, x::Symbol) = ccall(:jl_symbol_name, Ptr{UInt8}, (Any,), x)
3,542,087✔
61
unsafe_convert(::Type{Ptr{Int8}}, x::Symbol) = ccall(:jl_symbol_name, Ptr{Int8}, (Any,), x)
383,984✔
62

63
cconvert(::Type{<:Ptr}, a::Array) = getfield(a, :ref)
2,187,052,862✔
64
unsafe_convert(::Type{Ptr{S}}, a::AbstractArray{T}) where {S,T} = convert(Ptr{S}, unsafe_convert(Ptr{T}, a))
9✔
65
unsafe_convert(::Type{Ptr{T}}, a::Array{T}) where {T} = unsafe_convert(Ptr{T}, a.ref)
15✔
66
unsafe_convert(::Type{Ptr{T}}, a::AbstractArray{T}) where {T} = error("conversion to pointer not defined for $(typeof(a))")
22✔
67
# TODO: add this deprecation to give a better error:
68
# cconvert(::Type{<:Ptr}, a::AbstractArray) = error("conversion to pointer not defined for $(typeof(a))")
69
# unsafe_convert(::Type{Ptr{T}}, a::AbstractArray{T}) where {T} = error("missing call to cconvert for call to unsafe_convert for AbstractArray")
70

71
cconvert(::Type{<:Ptr}, a::GenericMemory) = a
11,328,967✔
72
unsafe_convert(::Type{Ptr{Cvoid}}, a::GenericMemory{T}) where {T} = getfield(a, :ptr)
6,320,277✔
73
unsafe_convert(::Type{Ptr{T}}, a::GenericMemory) where {T} = convert(Ptr{T}, getfield(a, :ptr))
1,507,030,683✔
74

75
function unsafe_convert(::Type{Ptr{Cvoid}}, a::GenericMemoryRef{<:Any,T,Core.CPU}) where {T}
23,212✔
76
    mem = getfield(a, :mem)
2,397,917,593✔
77
    offset = getfield(a, :ptr_or_offset)
2,455,403,271✔
78
    MemT = typeof(mem)
2,397,916,634✔
79
    arrayelem = datatype_arrayelem(MemT)
2,397,914,702✔
80
    elsz = datatype_layoutsize(MemT)
2,397,911,902✔
81
    isboxed = 1; isunion = 2
2,397,911,444✔
82
    if arrayelem == isunion || elsz == 0
2,397,911,866✔
83
        offset = UInt(offset) * elsz
3,173,392✔
84
        offset += unsafe_convert(Ptr{Cvoid}, mem)
3,173,392✔
85
    end
86
    return offset
2,397,915,165✔
87
end
88
unsafe_convert(::Type{Ptr{T}}, a::GenericMemoryRef) where {T} = convert(Ptr{T}, unsafe_convert(Ptr{Cvoid}, a))
255,186,311✔
89

90
# unsafe pointer to array conversions
91
"""
92
    unsafe_wrap(Array, pointer::Ptr{T}, dims; own = false)
93

94
Wrap a Julia `Array` object around the data at the address given by `pointer`,
95
without making a copy.  The pointer element type `T` determines the array
96
element type. `dims` is either an integer (for a 1d array) or a tuple of the array dimensions.
97
`own` optionally specifies whether Julia should take ownership of the memory,
98
calling `free` on the pointer when the array is no longer referenced.
99

100
This function is labeled "unsafe" because it will crash if `pointer` is not
101
a valid memory address to data of the requested length. Unlike [`unsafe_load`](@ref)
102
and [`unsafe_store!`](@ref), the programmer is responsible also for ensuring that the
103
underlying data is not accessed through two arrays of different element type, similar
104
to the strict aliasing rule in C.
105
"""
106
function unsafe_wrap(::Union{Type{Array},Type{Array{T}},Type{Array{T,N}}},
101,183✔
107
                     p::Ptr{T}, dims::NTuple{N,Int}; own::Bool = false) where {T,N}
108
    ccall(:jl_ptr_to_array, Array{T,N}, (Any, Ptr{Cvoid}, Any, Int32),
101,183✔
109
          Array{T,N}, p, dims, own)
110
end
111
function unsafe_wrap(::Union{Type{Array},Type{Array{T}},Type{Array{T,1}}},
184,140✔
112
                     p::Ptr{T}, d::Integer; own::Bool = false) where {T}
113
    ccall(:jl_ptr_to_array_1d, Array{T,1},
184,140✔
114
          (Any, Ptr{Cvoid}, Csize_t, Cint), Array{T,1}, p, d, own)
115
end
116
function unsafe_wrap(::Union{Type{GenericMemory{kind,<:Any,Core.CPU}},Type{GenericMemory{kind,T,Core.CPU}}},
3✔
117
                     p::Ptr{T}, dims::Tuple{Int}; own::Bool = false) where {kind,T}
118
    ccall(:jl_ptr_to_genericmemory, Ref{GenericMemory{kind,T,Core.CPU}},
3✔
119
          (Any, Ptr{Cvoid}, Csize_t, Cint), GenericMemory{kind,T,Core.CPU}, p, dims[1], own)
120
end
121
function unsafe_wrap(::Union{Type{GenericMemory{kind,<:Any,Core.CPU}},Type{GenericMemory{kind,T,Core.CPU}}},
×
122
                     p::Ptr{T}, d::Integer; own::Bool = false) where {kind,T}
123
    ccall(:jl_ptr_to_genericmemory, Ref{GenericMemory{kind,T,Core.CPU}},
×
124
          (Any, Ptr{Cvoid}, Csize_t, Cint), GenericMemory{kind,T,Core.CPU}, p, d, own)
125
end
126
unsafe_wrap(Atype::Union{Type{Array},Type{Array{T}},Type{Array{T,N}},Type{GenericMemory{kind,<:Any,Core.CPU}},Type{GenericMemory{kind,T,Core.CPU}}} where {kind},
×
127
            p::Ptr{T}, dims::NTuple{N,<:Integer}; own::Bool = false) where {T,N} =
196,966✔
128
    unsafe_wrap(Atype, p, convert(Tuple{Vararg{Int}}, dims), own = own)
129

130

131
"""
132
    unsafe_load(p::Ptr{T}, i::Integer=1)
133
    unsafe_load(p::Ptr{T}, order::Symbol)
134
    unsafe_load(p::Ptr{T}, i::Integer, order::Symbol)
135

136
Load a value of type `T` from the address of the `i`th element (1-indexed) starting at `p`.
137
This is equivalent to the C expression `p[i-1]`. Optionally, an atomic memory ordering can
138
be provided.
139

140
The `unsafe` prefix on this function indicates that no validation is performed on the
141
pointer `p` to ensure that it is valid. Like C, the programmer is responsible for ensuring
142
that referenced memory is not freed or garbage collected while invoking this function.
143
Incorrect usage may segfault your program or return garbage answers. Unlike C, dereferencing
144
memory region allocated as different type may be valid provided that the types are compatible.
145

146
!!! compat "Julia 1.10"
147
     The `order` argument is available as of Julia 1.10.
148

149
See also: [`atomic`](@ref)
150
"""
151
unsafe_load(p::Ptr, i::Integer=1) = pointerref(p, Int(i), 1)
3,917,503,990✔
152
unsafe_load(p::Ptr, order::Symbol) = atomic_pointerref(p, order)
232,148,183✔
153
function unsafe_load(p::Ptr, i::Integer, order::Symbol)
×
154
    unsafe_load(p + (elsize(typeof(p)) * (Int(i) - 1)), order)
×
155
end
156

157
"""
158
    unsafe_store!(p::Ptr{T}, x, i::Integer=1)
159
    unsafe_store!(p::Ptr{T}, x, order::Symbol)
160
    unsafe_store!(p::Ptr{T}, x, i::Integer, order::Symbol)
161

162
Store a value of type `T` to the address of the `i`th element (1-indexed) starting at `p`.
163
This is equivalent to the C expression `p[i-1] = x`. Optionally, an atomic memory ordering
164
can be provided.
165

166
The `unsafe` prefix on this function indicates that no validation is performed on the
167
pointer `p` to ensure that it is valid. Like C, the programmer is responsible for ensuring
168
that referenced memory is not freed or garbage collected while invoking this function.
169
Incorrect usage may segfault your program. Unlike C, storing memory region allocated as
170
different type may be valid provided that the types are compatible.
171

172
!!! compat "Julia 1.10"
173
     The `order` argument is available as of Julia 1.10.
174

175
See also: [`atomic`](@ref)
176
"""
177
unsafe_store!(p::Ptr{Any}, @nospecialize(x), i::Integer=1) = pointerset(p, x, Int(i), 1)
3✔
178
unsafe_store!(p::Ptr{T}, x, i::Integer=1) where {T} = pointerset(p, convert(T,x), Int(i), 1)
1,608,576,183✔
179
unsafe_store!(p::Ptr{T}, x, order::Symbol) where {T} = atomic_pointerset(p, x isa T ? x : convert(T,x), order)
142,975✔
180
function unsafe_store!(p::Ptr, x, i::Integer, order::Symbol)
×
181
    unsafe_store!(p + (elsize(typeof(p)) * (Int(i) - 1)), x, order)
×
182
end
183

184
"""
185
    unsafe_modify!(p::Ptr{T}, op, x, [order::Symbol])::Pair
186

187
These atomically perform the operations to get and set a memory address after applying
188
the function `op`. If supported by the hardware (for example, atomic increment), this may be
189
optimized to the appropriate hardware instruction, otherwise its execution will be
190
similar to:
191

192
    y = unsafe_load(p)
193
    z = op(y, x)
194
    unsafe_store!(p, z)
195
    return y => z
196

197
The `unsafe` prefix on this function indicates that no validation is performed on the
198
pointer `p` to ensure that it is valid. Like C, the programmer is responsible for ensuring
199
that referenced memory is not freed or garbage collected while invoking this function.
200
Incorrect usage may segfault your program.
201

202
!!! compat "Julia 1.10"
203
     This function requires at least Julia 1.10.
204

205
See also: [`modifyproperty!`](@ref Base.modifyproperty!), [`atomic`](@ref)
206
"""
207
function unsafe_modify!(p::Ptr, op, x, order::Symbol=:not_atomic)
21✔
208
    return atomic_pointermodify(p, op, x, order)
93✔
209
end
210

211
"""
212
    unsafe_replace!(p::Ptr{T}, expected, desired,
213
                   [success_order::Symbol[, fail_order::Symbol=success_order]]) -> (; old, success::Bool)
214

215
These atomically perform the operations to get and conditionally set a memory address to
216
a given value. If supported by the hardware, this may be optimized to the appropriate
217
hardware instruction, otherwise its execution will be similar to:
218

219
    y = unsafe_load(p, fail_order)
220
    ok = y === expected
221
    if ok
222
        unsafe_store!(p, desired, success_order)
223
    end
224
    return (; old = y, success = ok)
225

226
The `unsafe` prefix on this function indicates that no validation is performed on the
227
pointer `p` to ensure that it is valid. Like C, the programmer is responsible for ensuring
228
that referenced memory is not freed or garbage collected while invoking this function.
229
Incorrect usage may segfault your program.
230

231
!!! compat "Julia 1.10"
232
     This function requires at least Julia 1.10.
233

234
See also: [`replaceproperty!`](@ref Base.replaceproperty!), [`atomic`](@ref)
235
"""
236
function unsafe_replace!(p::Ptr{T}, expected, desired, success_order::Symbol=:not_atomic, fail_order::Symbol=success_order) where {T}
6✔
237
    @inline
87✔
238
    xT = desired isa T ? desired : convert(T, desired)
87✔
239
    return atomic_pointerreplace(p, expected, xT, success_order, fail_order)
87✔
240
end
241
function unsafe_replace!(p::Ptr{Any}, @nospecialize(expected), @nospecialize(desired), success_order::Symbol=:not_atomic, fail_order::Symbol=success_order)
242
    return atomic_pointerreplace(p, expected, desired, success_order, fail_order)
15✔
243
end
244

245
"""
246
    unsafe_swap!(p::Ptr{T}, x, [order::Symbol])
247

248
These atomically perform the operations to simultaneously get and set a memory address.
249
If supported by the hardware, this may be optimized to the appropriate hardware
250
instruction, otherwise its execution will be similar to:
251

252
    y = unsafe_load(p)
253
    unsafe_store!(p, x)
254
    return y
255

256
The `unsafe` prefix on this function indicates that no validation is performed on the
257
pointer `p` to ensure that it is valid. Like C, the programmer is responsible for ensuring
258
that referenced memory is not freed or garbage collected while invoking this function.
259
Incorrect usage may segfault your program.
260

261
!!! compat "Julia 1.10"
262
     This function requires at least Julia 1.10.
263

264
See also: [`swapproperty!`](@ref Base.swapproperty!), [`atomic`](@ref)
265
"""
266
function unsafe_swap!(p::Ptr{Any}, x, order::Symbol=:not_atomic)
267
    return atomic_pointerswap(p, x, order)
6✔
268
end
269
function unsafe_swap!(p::Ptr{T}, x, order::Symbol=:not_atomic) where {T}
3✔
270
    @inline
33✔
271
    xT = x isa T ? x : convert(T, x)
33✔
272
    return atomic_pointerswap(p, xT, order)
33✔
273
end
274

275
# convert a raw Ptr to an object reference, and vice-versa
276
"""
277
    unsafe_pointer_to_objref(p::Ptr)
278

279
Convert a `Ptr` to an object reference. Assumes the pointer refers to a valid heap-allocated
280
Julia object. If this is not the case, undefined behavior results, hence this function is
281
considered "unsafe" and should be used with care.
282

283
See also [`pointer_from_objref`](@ref).
284
"""
285
unsafe_pointer_to_objref(x::Ptr) = ccall(:jl_value_ptr, Any, (Ptr{Cvoid},), x)
2,324,074✔
286

287
"""
288
    pointer_from_objref(x)
289

290
Get the memory address of a Julia object as a `Ptr`. The existence of the resulting `Ptr`
291
will not protect the object from garbage collection, so you must ensure that the object
292
remains referenced for the whole time that the `Ptr` will be used.
293

294
This function may not be called on immutable objects, since they do not have
295
stable memory addresses.
296

297
See also [`unsafe_pointer_to_objref`](@ref).
298
"""
299
function pointer_from_objref(@nospecialize(x))
25,956✔
300
    @inline
115,245,058✔
301
    ismutable(x) || error("pointer_from_objref cannot be used on immutable objects")
115,244,389✔
302
    ccall(:jl_value_ptr, Ptr{Cvoid}, (Any,), x)
155,915,292✔
303
end
304

305
## limited pointer arithmetic & comparison ##
306

307
isequal(x::Ptr, y::Ptr) = (x === y)
3✔
308
isless(x::Ptr{T}, y::Ptr{T}) where {T} = x < y
3✔
309

310
==(x::Ptr, y::Ptr) = UInt(x) == UInt(y)
745,200,421✔
311
<(x::Ptr,  y::Ptr) = UInt(x) < UInt(y)
5,387,384✔
312
-(x::Ptr,  y::Ptr) = UInt(x) - UInt(y)
11,416,352✔
313

314
+(x::Ptr, y::Integer) = add_ptr(x, (y % UInt) % UInt)
3,066,241,432✔
315
-(x::Ptr, y::Integer) = sub_ptr(x, (y % UInt) % UInt)
770,149,168✔
316
+(x::Integer, y::Ptr) = y + x
3,173,395✔
317

318
unsigned(x::Ptr) = UInt(x)
×
319
signed(x::Ptr) = Int(x)
×
STATUS · Troubleshooting · Open an Issue · Sales · Support · CAREERS · ENTERPRISE · START FREE · SCHEDULE DEMO
ANNOUNCEMENTS · TWITTER · TOS & SLA · Supported CI Services · What's a CI service? · Automated Testing

© 2026 Coveralls, Inc