If I have code like
class Stream
{
var stream:z_stream
}
var stream:Stream
mutating
func foo1()
{
withUnsafeMutablePointer(to: &self.stream.stream)
{
(storage:UnsafeMutablePointer<z_stream>) in
bar1(storage)
}
}
mutating
func foo2()
{
withUnsafeMutablePointer(to: &self.stream.stream)
{
(storage:UnsafeMutablePointer<z_stream>) in
bar2(storage)
}
do I have any guarantees about the location of storage between foo1 and foo2? the reason I’m asking is because zlib for some reason stores internally a pointer to something in the z_stream struct and it checks the consistency of this pointer in every library method. i already figured out a long time ago the z_stream has to be wrapped in a reference type to keep it from getting copied, and the class wrapper seems to fix everything for now, but is this defined behavior, especially since the z_stream itself is still a (C) struct?
jrose
(Jordan Rose)
2
I believe the inout-to-pointer conversion for a final stored class property gives you a consistent address each time, but otherwise it's not guaranteed. @Joe_Groff, @John_McCall, confirm/deny?
Joe_Groff
(Joe Groff)
3
You'll get a consistent identity, but you still shouldn't read or write the memory outside of a formal access.
1 Like
everyone keeps talking about “& means copy-back semantics” and i always assumed that meant we have to assume this is taking place formally
var local:z_stream = self.stream.stream
bar1(Builtin.address(of: local)) // whatever this builtin is called
self.stream.stream = local
which is “supposed” to fail since the library pointer and passed pointer are no longer consistent
Joe_Groff
(Joe Groff)
6
An access through a normal property read or write, inout-to-pointer call, or inside the confines of a withUnsafePointer/Bytes call. Even if you get the same pointer, code that reads or writes through the pointer outside of withUnsafe* may cause unpredictable behavior:
final class C { var x: Int }
let x = C()
var p: UnsafeRawPointer?
withUnsafeBytes(of: &x.x) {
p = $0.startAddress
print(p.load(as: Int.self)) // ok
}
print(p.load(as: Int.self)) // not ok
withUnsafeBytes(of: &x.x) {
print(p.load(as: Int.self)) // probably ok
}
does that mean i have to allocate it manually if zlib is storing pointers to it internally?
1 Like
Joe_Groff
(Joe Groff)
8
Yeah, or expand your withUnsafePointer scope to cover the duration of time zlib needs access to the memory.
2 Likes