chenBright commented on code in PR #3685:
URL: https://github.com/apache/brpc/pull/3685#discussion_r4454244354


##########
src/butil/memory/scoped_ptr.h:
##########
@@ -326,37 +297,35 @@ class scoped_ptr {
   // Constructor.  Allows initialization of a stateful deleter.
   scoped_ptr(element_type* p, const D& d) : impl_(p, d) { }
 
-  // Constructor.  Allows construction from a scoped_ptr rvalue for a
-  // convertible type and deleter.
-  //
-  // IMPLEMENTATION NOTE: C++11 unique_ptr<> keeps this constructor distinct
-  // from the normal move constructor. By C++11 20.7.1.2.1.21, this constructor
-  // has different post-conditions if D is a reference type. Since this
-  // implementation does not support deleters with reference type,
-  // we do not need a separate move constructor allowing us to avoid one
-  // use of SFINAE. You only need to care about this if you modify the
-  // implementation of scoped_ptr.
-  template <typename U, typename V>
-  scoped_ptr(scoped_ptr<U, V> other) : impl_(&other.impl_) {
-    COMPILE_ASSERT(!butil::is_array<U>::value, U_cannot_be_an_array);
-  }
+  scoped_ptr(const scoped_ptr&) = delete;
+  scoped_ptr& operator=(const scoped_ptr&) = delete;
 
-  // Constructor.  Move constructor for C++03 move emulation of this type.
-  scoped_ptr(RValue rvalue) : impl_(&rvalue.object->impl_) { }
+  // Move operations copy the deleter to preserve existing behavior. Move-only
+  // deleters are intentionally unsupported.
+  scoped_ptr(scoped_ptr&& other) : impl_(&other.impl_) { }
 
-  // operator=.  Allows assignment from a scoped_ptr rvalue for a convertible
-  // type and deleter.
-  //
-  // IMPLEMENTATION NOTE: C++11 unique_ptr<> keeps this operator= distinct from
-  // the normal move assignment operator. By C++11 20.7.1.2.3.4, this templated
-  // form has different requirements on for move-only Deleters. Since this
-  // implementation does not support move-only Deleters, we do not need a
-  // separate move assignment operator allowing us to avoid one use of SFINAE.
-  // You only need to care about this if you modify the implementation of
-  // scoped_ptr.
-  template <typename U, typename V>
-  scoped_ptr& operator=(scoped_ptr<U, V> rhs) {
-    COMPILE_ASSERT(!butil::is_array<U>::value, U_cannot_be_an_array);
+  scoped_ptr& operator=(scoped_ptr&& rhs) {
+    if (this != &rhs) {
+      impl_.TakeState(&rhs.impl_);

Review Comment:
   When the move source is a member of an object owned by the destination, for 
example `head = std::move(head->next)` with a stateful deleter, `rhs` is 
destroyed during assignment: `TakeState` first deletes the old node via 
`reset(other->release())`, then reads `other->get_deleter()` from that node, so 
copying the deleter accesses freed memory. The original `Pass()` and by-value 
parameter first established an independent temporary owner, avoiding this 
issue. Please preserve the source's complete ownership state before clearing 
the old destination, and add a regression test for a nested source; converting 
assignment uses the same path.



##########
src/butil/memory/scoped_vector.h:
##########
@@ -37,13 +34,16 @@ class ScopedVector {
 
   ScopedVector() {}
   ~ScopedVector() { clear(); }
-  ScopedVector(RValue other) { swap(*other.object); }
-#if __cplusplus >= 201103L  // >= C++11
+  ScopedVector(const ScopedVector&) = delete;
+  ScopedVector& operator=(const ScopedVector&) = delete;
+  ScopedVector(ScopedVector&& other) noexcept { swap(other); }
   ScopedVector(std::initializer_list<value_type> il) : v_(il) {}
-#endif
 
-  ScopedVector& operator=(RValue rhs) {
-    swap(*rhs.object);
+  ScopedVector& operator=(ScopedVector&& rhs) {
+    if (this != &rhs) {
+      clear();
+      swap(rhs);

Review Comment:
   If the move source is inside an element owned by the destination, for 
example `nodes = std::move(nodes[0]->children)`, `clear()` first deletes the 
parent node, destroys `rhs`, and frees its child nodes. The subsequent 
`swap(rhs)` therefore accesses a freed object. The old `children.Pass()` first 
moved the child nodes into an independent temporary container, avoiding 
premature destruction of the source. Please first move-construct a temporary 
container, then swap it with the destination and clear the old elements, and 
add a test for this parent-child container scenario.



-- 
This is an automated message from the Apache Git Service.
To respond to the message, please log on to GitHub and use the
URL above to go to the specific comment.

To unsubscribe, e-mail: [email protected]

For queries about this service, please contact Infrastructure at:
[email protected]


---------------------------------------------------------------------
To unsubscribe, e-mail: [email protected]
For additional commands, e-mail: [email protected]

Reply via email to