diff --git a/rtc_base/buffer.h b/rtc_base/buffer.h index 9bf96cd146..2707cdfb86 100644 --- a/rtc_base/buffer.h +++ b/rtc_base/buffer.h @@ -152,7 +152,9 @@ class BufferT { RTC_DCHECK(buf.IsConsistent()); size_ = buf.size_; capacity_ = buf.capacity_; - data_ = std::move(buf.data_); + using std::swap; + swap(data_, buf.data_); + buf.data_.reset(); buf.OnMovedFrom(); return *this; } @@ -399,6 +401,7 @@ class BufferT { // Called when *this has been moved from. Conceptually it's a no-op, but we // can mutate the state slightly to help subsequent sanity checks catch bugs. void OnMovedFrom() { + RTC_DCHECK(!data_); // Our heap block should have been stolen. #if RTC_DCHECK_IS_ON // Ensure that *this is always inconsistent, to provoke bugs. size_ = 1; diff --git a/rtc_base/buffer_unittest.cc b/rtc_base/buffer_unittest.cc index 1c3abfd08f..b2f47c16ec 100644 --- a/rtc_base/buffer_unittest.cc +++ b/rtc_base/buffer_unittest.cc @@ -185,6 +185,17 @@ TEST(BufferTest, TestMoveAssign) { EXPECT_TRUE(buf1.empty()); } +TEST(BufferTest, TestMoveAssignSelf) { + // Move self-assignment isn't required to produce a meaningful state, but + // should not leave the object in an inconsistent state. (Such inconsistent + // state could be caught by the DCHECKs and/or by the leak checker.) We need + // to be sneaky when testing this; if we're doing a too-obvious + // move-assign-to-self, clang's -Wself-move triggers at compile time. + Buffer buf(kTestData, 3, 40); + Buffer* buf_ptr = &buf; + buf = std::move(*buf_ptr); +} + TEST(BufferTest, TestSwap) { Buffer buf1(kTestData, 3); Buffer buf2(kTestData, 6, 40);