From cc25516d3e8e5f058356b8dc263b877ff2b07117 Mon Sep 17 00:00:00 2001 From: Lukas Bergdoll Date: Thu, 14 Sep 2017 18:22:55 +0200 Subject: [PATCH] [C++] Fix DetachedBuffer move assignment lifetime (#4437) * Fix DetachedBuffer move assignment lifetime DetachedBuffer move assignment now destroys it's own content, rather than waiting for the destructor of other. See more under #4435 Add missing function return type * Rename empty_assign to reset Reset after destroy reset() now operates on itself --- include/flatbuffers/flatbuffers.h | 53 ++++++++++++++++++++----------- 1 file changed, 34 insertions(+), 19 deletions(-) diff --git a/include/flatbuffers/flatbuffers.h b/include/flatbuffers/flatbuffers.h index ab17b6e0b..627f097e3 100644 --- a/include/flatbuffers/flatbuffers.h +++ b/include/flatbuffers/flatbuffers.h @@ -445,32 +445,26 @@ class DetachedBuffer { : allocator_(other.allocator_), own_allocator_(other.own_allocator_), buf_(other.buf_), reserved_(other.reserved_), cur_(other.cur_), size_(other.size_) { - other.allocator_ = nullptr; - other.own_allocator_ = false; - other.buf_ = nullptr; - other.reserved_ = 0; - other.cur_ = nullptr; - other.size_ = 0; + other.reset(); } DetachedBuffer &operator=(DetachedBuffer &&other) { - std::swap(allocator_, other.allocator_); - std::swap(own_allocator_, other.own_allocator_); - std::swap(buf_, other.buf_); - std::swap(reserved_, other.reserved_); - std::swap(cur_, other.cur_); - std::swap(size_, other.size_); + destroy(); + + allocator_ = other.allocator_; + own_allocator_ = other.own_allocator_; + buf_ = other.buf_; + reserved_ = other.reserved_; + cur_ = other.cur_; + size_ = other.size_; + + other.reset(); + return *this; } ~DetachedBuffer() { - if (buf_) { - assert(allocator_); - allocator_->deallocate(buf_, reserved_); - } - if (own_allocator_ && allocator_) { - delete allocator_; - } + destroy(); } const uint8_t *data() const { @@ -515,6 +509,27 @@ class DetachedBuffer { size_t reserved_; uint8_t *cur_; size_t size_; + + inline void destroy() { + if (buf_) { + assert(allocator_); + allocator_->deallocate(buf_, reserved_); + } + if (own_allocator_ && allocator_) { + delete allocator_; + } + + reset(); + } + + inline void reset() { + allocator_ = nullptr; + own_allocator_ = false; + buf_ = nullptr; + reserved_ = 0; + cur_ = nullptr; + size_ = 0; + } }; // This is a minimal replication of std::vector functionality,