Is it safe to deinitialize() uninitialized memory if it was bound to a trivial type?

I have been reading related threads and I have seen it clearly stated in several places (for example here) that it is safe to skip the call to deinitialize() on memory if it is bound to a “trivial type”, which I understand to basically mean that the memory contains no ARC managed references. I am additionally curious about how initialize/deinitialize interact with reference counting, but that’s not the point of this post.

What I want to verify is: is it also safe to deinitialize() a buffer that is partially initialized?

Other pointer documentation has language that carves out exceptions relating to trivial types, but the documentation for UnsafeMutableBufferPointer.deinitialize() only says:

All buffer elements must already be initialized.

My guess is that by the same token as it is safe to skip deinitialization entirely for trivially typed memory, it is also safe to deinitialize() when none or only part of the buffer has been initialized. Is this true?

This also includes noncopyable types that have deinits now. Plenty of imported C++ types that also have custom destructors require deinitialization.

No! Deinitialization assumes initialized state, so calling it on uninitialized memory is undefined behavior! For example:

struct NC: ~Copyable {
  let ptr: UnsafeRawPointer

  deinit {
    foo(ptr)
  }
}

Imagine having a buffer of NCs, if you call deinitialize on uninitialized parts, it will call this deinit for every item and for the uninitialized parts it will call foo by passing random bytes that it thinks is a pointer. This is not good!

3 Likes

My question though is specifically whether it is safe to call deinitialize() on a partially initialized buffer of trivial type. In my case it is an UnsafeMutableBufferPointer<UInt8>. I’m passing it to compression_stream_process which will write into it, possibly not filling it up, and then I need to deallocate it, and I’m wondering if I need to keep track of how much of the buffer got filled up and call deinitializeElement(at:) for each byte, or if I can safely call outputBuffer.deinitialize() no matter what.

Yes, it’s fine to call deinitialize on uninitialized trivial types.

3 Likes

Oh, perhaps I misunderstood. Are you saying that the definition of “trivial” now includes noncopyable types (even if they have deinits)?

Nice, thanks

No, I was saying that noncopyable types with deinits are another form of non-trivial types that don’t necessarily include ARC references.

4 Likes