org-howto/articles/2024/01/zstream-isnt-moveable.org

2.5 KiB

[2024] zlib z_stream isn't moveable

#

#

#

#

#

#

TL;DR

Be aware that zlib's z_stream struct cannot be moved. Presume it contains internal pointers to itself.

Setup

  • Using zstreambuf (provided as byproduct of my cmake-examples project) I ran into errors after move assignment.
  • Making zstreambuf.open() work with a zstreambuf that's already been used for i/o.
  • Attempted to cleanup state within zstreambuf.close(), using move assignment on buffered_inflate_zstream and buffered_deflate_zstream.

Problem + Diagnosis

  • Unit testing revealed that uncompress failed after second zstreambuf.open().
  • It turns out that although zlib's z_stream struct is fully exposed (to work with zlib, application code should declare a variable with type z_stream), the z_stream struct can't be moved to another location. Presumably at least one of (::deflateInit2(), ::inflateInit2()) does some address-dependent computation involving one or more z_stream members.

Solution

  • Replace z_stream member with a pointer:

    Instead of:

      // compression/include/compression/base_zstream.hpp
    
      #include <zlib.h>
    
      struct base_zstream {
          // ...omitted...
    
          z_stream zstream_;
      };

    write:

      // compression/include/compression/base_zstream.hpp
    
      #include <utility>
    
      struct base_zstream {
          // ...omitted...
    
          std::unique_ptr<z_stream> p_native_zs_;
      };

    Then implement ::swap() etc by swapping pointers.