Fix leak in __enable_weak_this(). Thanks to Arthur O'Dwyer for finding it.

git-svn-id: https://llvm.org/svn/llvm-project/libcxx/trunk@271487 91177308-0d34-0410-b5e6-96231b3b80d8
This commit is contained in:
Eric Fiselier
2016-06-02 04:57:00 +00:00
parent a2cc95e5b7
commit b36940bb34
2 changed files with 37 additions and 3 deletions

View File

@@ -4122,9 +4122,11 @@ private:
{
if (__e && __e->__weak_this_.expired())
{
__e->__weak_this_.__ptr_ = const_cast<_Yp*>(static_cast<const _Yp*>(__e));
__e->__weak_this_.__cntrl_ = __cntrl_;
weak_ptr<_Yp> __tmp;
__tmp.__ptr_ = const_cast<_Yp*>(static_cast<const _Yp*>(__e));
__tmp.__cntrl_ = __cntrl_;
__cntrl_->__add_weak();
__e->__weak_this_.swap(__tmp);
}
}

View File

@@ -26,6 +26,7 @@
#include <cassert>
#include "test_macros.h"
#include "count_new.hpp"
struct T
: public std::enable_shared_from_this<T>
@@ -62,7 +63,7 @@ int main()
// * Using 'weak_from_this().expired()' in C++17.
// * Using 'shared_from_this()' in all dialects.
{
assert(globalMemCounter.checkOutstandingNewEq(0));
T* ptr = new T;
std::shared_ptr<T> s(ptr);
{
@@ -87,6 +88,37 @@ int main()
}
}
#endif
s.reset();
assert(globalMemCounter.checkOutstandingNewEq(0));
}
// Test LWG issue 2529 again. This time check that an expired pointer
// is replaced.
{
assert(globalMemCounter.checkOutstandingNewEq(0));
T* ptr = new T;
std::weak_ptr<T> weak;
{
std::shared_ptr<T> s(ptr, &nullDeleter);
assert(ptr->shared_from_this() == s);
weak = s;
assert(!weak.expired());
}
assert(weak.expired());
weak.reset();
#ifndef TEST_HAS_NO_EXCEPTIONS
try {
ptr->shared_from_this();
assert(false);
} catch (std::bad_weak_ptr const&) {
} catch (...) { assert(false); }
#endif
{
std::shared_ptr<T> s2(ptr, &nullDeleter);
assert(ptr->shared_from_this() == s2);
}
delete ptr;
assert(globalMemCounter.checkOutstandingNewEq(0));
}
// Test weak_from_this_methods
#if TEST_STD_VER > 14