Fix bug - memory leak when move-constructing a string with unequal allocator. Thanks to Thomas Koeppe for the report

llvm-svn: 213269
This commit is contained in:
Marshall Clow 2014-07-17 15:32:20 +00:00
parent 18cfe7d634
commit 3dd8846840
2 changed files with 26 additions and 14 deletions
libcxx
include
test/strings/basic.string/string.cons

View File

@ -1031,16 +1031,16 @@ __str_rfind(const _CharT *__p, _SizeT __sz,
_CharT __c, _SizeT __pos) _NOEXCEPT _CharT __c, _SizeT __pos) _NOEXCEPT
{ {
if (__sz < 1) if (__sz < 1)
return __npos; return __npos;
if (__pos < __sz) if (__pos < __sz)
++__pos; ++__pos;
else else
__pos = __sz; __pos = __sz;
for (const _CharT* __ps = __p + __pos; __ps != __p;) for (const _CharT* __ps = __p + __pos; __ps != __p;)
{ {
if (_Traits::eq(*--__ps, __c)) if (_Traits::eq(*--__ps, __c))
return static_cast<_SizeT>(__ps - __p); return static_cast<_SizeT>(__ps - __p);
} }
return __npos; return __npos;
} }
@ -2136,11 +2136,13 @@ inline _LIBCPP_INLINE_VISIBILITY
basic_string<_CharT, _Traits, _Allocator>::basic_string(basic_string&& __str, const allocator_type& __a) basic_string<_CharT, _Traits, _Allocator>::basic_string(basic_string&& __str, const allocator_type& __a)
: __r_(__a) : __r_(__a)
{ {
if (__a == __str.__alloc() || !__str.__is_long()) if (__str.__is_long() && __a != __str.__alloc()) // copy, not move
__r_.first().__r = __str.__r_.first().__r;
else
__init(_VSTD::__to_raw_pointer(__str.__get_long_pointer()), __str.__get_long_size()); __init(_VSTD::__to_raw_pointer(__str.__get_long_pointer()), __str.__get_long_size());
__str.__zero(); else
{
__r_.first().__r = __str.__r_.first().__r;
__str.__zero();
}
#if _LIBCPP_DEBUG_LEVEL >= 2 #if _LIBCPP_DEBUG_LEVEL >= 2
__get_db()->__insert_c(this); __get_db()->__insert_c(this);
if (__is_long()) if (__is_long())

View File

@ -45,6 +45,16 @@ int main()
test(S("1"), A(5)); test(S("1"), A(5));
test(S("1234567890123456789012345678901234567890123456789012345678901234567890"), A(7)); test(S("1234567890123456789012345678901234567890123456789012345678901234567890"), A(7));
} }
int alloc_count = test_alloc_base::alloc_count;
{
typedef test_allocator<char> A;
typedef std::basic_string<char, std::char_traits<char>, A> S;
S s1 ( "Twas brillig, and the slivy toves did gyre and gymbal in the wabe" );
S s2 (std::move(s1), A(1));
}
assert ( test_alloc_base::alloc_count == alloc_count );
#if __cplusplus >= 201103L #if __cplusplus >= 201103L
{ {
typedef min_allocator<char> A; typedef min_allocator<char> A;