Index: base/memory/scoped_ptr_unittest.cc |
diff --git a/base/memory/scoped_ptr_unittest.cc b/base/memory/scoped_ptr_unittest.cc |
index 71d995c452e826ad1faeb28f315433077f338e88..eb5bf000c48596d12ae97c59aad7c7eaf734ea06 100644 |
--- a/base/memory/scoped_ptr_unittest.cc |
+++ b/base/memory/scoped_ptr_unittest.cc |
@@ -709,10 +709,20 @@ TEST(ScopedPtrTest, ReferenceCycle) { |
a->b.reset(new StructB); |
a->b->a.reset(a); |
- // Break the cycle by calling reset(). This will cause |a| (and hence, |a.b|) |
+ // Break the cycle by calling reset(). This will cause |a| (and hence, |a->b|) |
// to be deleted before the call to reset() returns. This tests that the |
// implementation of scoped_ptr::reset() doesn't access |this| after it |
// deletes the underlying pointer. This behaviour is consistent with the |
// definition of unique_ptr::reset in C++11. |
a->b.reset(); |
+ |
+ // Go again, but this time, break the cycle by invoking |a|'s destructor. This |
+ // tests that the implementation of ~scoped_ptr doesn't infinitely recurse |
+ // into the destructors of |a| and |a->b|. Note, deleting |a| instead will |
+ // cause |a| to be double-free'd because |a->b| owns |a| and deletes it via |
+ // its destructor. |
+ a = new StructA; |
+ a->b.reset(new StructB); |
+ a->b->a.reset(a); |
+ a->~StructA(); |
} |