Skip to content

Commit e916fd9

Browse files
authored
Merge pull request #72 from c42f/cjf/gc-preserve
Add `GC.@preserve` where `pointer()` is used
2 parents 430908a + c94f749 commit e916fd9

File tree

2 files changed

+42
-38
lines changed

2 files changed

+42
-38
lines changed

src/ZipFile.jl

Lines changed: 4 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -521,8 +521,10 @@ function _read(f::ReadableFile, a::Array{T}) where T
521521

522522
seek(f._io, f._datapos+f._zpos)
523523
b = unsafe_wrap(Array{UInt8, 1}, reinterpret(Ptr{UInt8}, pointer(a)), sizeof(a))
524-
read!(f._zio, b)
525-
update_reader!(f, b)
524+
GC.@preserve a begin
525+
read!(f._zio, b)
526+
update_reader!(f, b)
527+
end
526528

527529
return a
528530
end

src/Zlib.jl

Lines changed: 38 additions & 36 deletions
Original file line numberDiff line numberDiff line change
@@ -127,7 +127,7 @@ function write(w::Writer, p::Ptr, nb::Integer)
127127
w.strm.avail_in = nb
128128
outbuf = Vector{UInt8}(undef, 1024)
129129

130-
while true
130+
GC.@preserve outbuf while true
131131
w.strm.avail_out = length(outbuf)
132132
w.strm.next_out = pointer(outbuf)
133133

@@ -146,16 +146,20 @@ function write(w::Writer, p::Ptr, nb::Integer)
146146
break
147147
end
148148
end
149+
w.strm.next_in = C_NULL
150+
w.strm.next_out = C_NULL
149151
nb
150152
end
151153

152-
write(w::Writer, a::Array{UInt8}) = write(w, pointer(a), length(a))
154+
function write(w::Writer, a::Array{UInt8})
155+
GC.@preserve a write(w, pointer(a), length(a))
156+
end
153157

154158
# If this is not provided, Base.IO write methods will write
155159
# arrays one element at a time.
156160
function write(w::Writer, a::Array{T}) where T
157161
if isbits(T)
158-
write(w, pointer(a), length(a)*sizeof(T))
162+
GC.@preserve a write(w, pointer(a), length(a)*sizeof(T))
159163
else
160164
invoke(write, Tuple{IO,Array}, w, a)
161165
end
@@ -168,20 +172,11 @@ function write(w::Writer, a::SubArray{T,N,A}) where {T,N,A<:Array}
168172
end
169173
colsz = size(a,1)*sizeof(T)
170174
if N<=1
171-
return write(s, pointer(a, 1), colsz)
175+
return GC.@preserve a write(s, pointer(a, 1), colsz)
172176
else
173-
# WARNING: cartesianmap(f,dims) is deprecated, use for idx = CartesianRange(dims)
174-
# f(idx.I...)
175-
176-
if VERSION >= v"0.4.0-"
177-
for idx in CartesianRange(tuple(1, size(a)[2:end]...))
178-
write(w, pointer(a, idx.I), colsz)
179-
end
180-
else
181-
cartesianmap((idxs...)->write(w, pointer(a, idxs), colsz),
182-
tuple(1, size(a)[2:end]...))
177+
for idx in CartesianRange(tuple(1, size(a)[2:end]...))
178+
GC.@preserve a write(w, pointer(a, idx.I), colsz)
183179
end
184-
185180
return colsz*Base.trailingsize(a,2)
186181
end
187182
end
@@ -197,30 +192,34 @@ function close(w::Writer)
197192
w.closed = true
198193

199194
# flush zlib buffer using Z_FINISH
200-
inbuf = Vector{UInt8}(undef, 0)
201-
w.strm.next_in = pointer(inbuf)
202-
w.strm.avail_in = 0
195+
inbuf = Ref{UInt8}(0)
203196
outbuf = Vector{UInt8}(undef, 1024)
204-
ret = Z_OK
205-
while ret != Z_STREAM_END
206-
w.strm.avail_out = length(outbuf)
207-
w.strm.next_out = pointer(outbuf)
208-
ret = ccall((:deflate, libz),
209-
Int32, (Ptr{z_stream}, Int32),
210-
Ref(w.strm), Z_FINISH)
211-
if ret != Z_OK && ret != Z_STREAM_END
212-
error("Error in zlib deflate stream ($(ret)).")
213-
end
214-
n = length(outbuf) - w.strm.avail_out
215-
if n > 0 && write(w.io, outbuf[1:n]) != n
216-
error("short write")
197+
GC.@preserve inbuf outbuf begin
198+
w.strm.next_in = Base.unsafe_convert(Ptr{UInt8}, inbuf)
199+
w.strm.avail_in = 0
200+
ret = Z_OK
201+
while ret != Z_STREAM_END
202+
w.strm.avail_out = length(outbuf)
203+
w.strm.next_out = pointer(outbuf)
204+
ret = ccall((:deflate, libz),
205+
Int32, (Ptr{z_stream}, Int32),
206+
Ref(w.strm), Z_FINISH)
207+
if ret != Z_OK && ret != Z_STREAM_END
208+
error("Error in zlib deflate stream ($(ret)).")
209+
end
210+
n = length(outbuf) - w.strm.avail_out
211+
if n > 0 && write(w.io, outbuf[1:n]) != n
212+
error("short write")
213+
end
217214
end
218-
end
219215

220-
ret = ccall((:deflateEnd, libz), Int32, (Ptr{z_stream},), Ref(w.strm))
221-
if ret == Z_STREAM_ERROR
222-
error("Error: zlib deflate stream was prematurely freed.")
216+
ret = ccall((:deflateEnd, libz), Int32, (Ptr{z_stream},), Ref(w.strm))
217+
if ret == Z_STREAM_ERROR
218+
error("Error: zlib deflate stream was prematurely freed.")
219+
end
223220
end
221+
w.strm.next_in = C_NULL
222+
w.strm.next_out = C_NULL
224223
end
225224

226225

@@ -258,7 +257,8 @@ function fillbuf(r::Reader, minlen::Integer)
258257
r.strm.avail_in = length(input)
259258
#outbuf = Vector{UInt8}(undef, r.bufsize)
260259

261-
while true
260+
r_buf = r.buf # GC.@preserve only accepts symbols
261+
GC.@preserve input r_buf while true
262262
#r.strm.next_out = outbuf
263263
#r.strm.avail_out = length(outbuf)
264264
(r.strm.next_out, r.strm.avail_out) = Base.alloc_request(r.buf, convert(UInt, r.bufsize))
@@ -282,6 +282,8 @@ function fillbuf(r::Reader, minlen::Integer)
282282
end
283283
end
284284
end
285+
r.strm.next_in = C_NULL
286+
r.strm.next_out = C_NULL
285287

286288
if ret == Z_STREAM_END
287289
r.stream_end = true

0 commit comments

Comments
 (0)