vector.tcc (vector<>::_M_insert_aux): In C++0x mode, avoid a memory leak if the first __uninitialized_move_a throws.
2008-06-02 Paolo Carlini <paolo.carlini@oracle.com> * include/bits/vector.tcc (vector<>::_M_insert_aux): In C++0x mode, avoid a memory leak if the first __uninitialized_move_a throws. (vector<>::_M_fill_insert): Do not always copy to __x_copy, similarly to _M_insert_aux. * testsuite/23_containers/vector/modifiers/moveable.cc: Adjust. * testsuite/23_containers/vector/resize/moveable.cc: Likewise. From-SVN: r136277
This commit is contained in:
parent
690028435c
commit
d2219f89bf
|
@ -1,3 +1,12 @@
|
|||
2008-06-02 Paolo Carlini <paolo.carlini@oracle.com>
|
||||
|
||||
* include/bits/vector.tcc (vector<>::_M_insert_aux): In C++0x mode,
|
||||
avoid a memory leak if the first __uninitialized_move_a throws.
|
||||
(vector<>::_M_fill_insert): Do not always copy to __x_copy, similarly
|
||||
to _M_insert_aux.
|
||||
* testsuite/23_containers/vector/modifiers/moveable.cc: Adjust.
|
||||
* testsuite/23_containers/vector/resize/moveable.cc: Likewise.
|
||||
|
||||
2008-05-31 Paolo Carlini <paolo.carlini@oracle.com>
|
||||
Chris Jefferson <chris@bubblescope.net>
|
||||
|
||||
|
|
|
@ -1,6 +1,6 @@
|
|||
// Vector implementation (out of line) -*- C++ -*-
|
||||
|
||||
// Copyright (C) 2001, 2002, 2003, 2004, 2005, 2006, 2007
|
||||
// Copyright (C) 2001, 2002, 2003, 2004, 2005, 2006, 2007, 2008
|
||||
// Free Software Foundation, Inc.
|
||||
//
|
||||
// This file is part of the GNU ISO C++ Library. This library is free
|
||||
|
@ -305,22 +305,29 @@ _GLIBCXX_BEGIN_NESTED_NAMESPACE(std, _GLIBCXX_STD_D)
|
|||
{
|
||||
const size_type __len =
|
||||
_M_check_len(size_type(1), "vector::_M_insert_aux");
|
||||
const size_type __elems_before = __position - begin();
|
||||
pointer __new_start(this->_M_allocate(__len));
|
||||
pointer __new_finish(__new_start);
|
||||
try
|
||||
{
|
||||
// The order of the three operations is dictated by the C++0x
|
||||
// case, where the moves could alter a new element belonging
|
||||
// to the existing vector. This is an issue only for callers
|
||||
// taking the element by const lvalue ref (see 23.1/13).
|
||||
this->_M_impl.construct(__new_start + __elems_before,
|
||||
#ifdef __GXX_EXPERIMENTAL_CXX0X__
|
||||
this->_M_impl.construct(__new_start + (__position - begin()),
|
||||
std::forward<_Args>(__args)...);
|
||||
#else
|
||||
__x);
|
||||
#endif
|
||||
__new_finish = 0;
|
||||
|
||||
__new_finish =
|
||||
std::__uninitialized_move_a(this->_M_impl._M_start,
|
||||
__position.base(), __new_start,
|
||||
_M_get_Tp_allocator());
|
||||
#ifndef __GXX_EXPERIMENTAL_CXX0X__
|
||||
this->_M_impl.construct(__new_finish, __x);
|
||||
#endif
|
||||
++__new_finish;
|
||||
|
||||
__new_finish =
|
||||
std::__uninitialized_move_a(__position.base(),
|
||||
this->_M_impl._M_finish,
|
||||
|
@ -329,7 +336,10 @@ _GLIBCXX_BEGIN_NESTED_NAMESPACE(std, _GLIBCXX_STD_D)
|
|||
}
|
||||
catch(...)
|
||||
{
|
||||
std::_Destroy(__new_start, __new_finish, _M_get_Tp_allocator());
|
||||
if (!__new_finish)
|
||||
this->_M_impl.destroy(__new_start + __elems_before);
|
||||
else
|
||||
std::_Destroy(__new_start, __new_finish, _M_get_Tp_allocator());
|
||||
_M_deallocate(__new_start, __len);
|
||||
__throw_exception_again;
|
||||
}
|
||||
|
@ -351,15 +361,10 @@ _GLIBCXX_BEGIN_NESTED_NAMESPACE(std, _GLIBCXX_STD_D)
|
|||
{
|
||||
if (__n != 0)
|
||||
{
|
||||
#ifdef __GXX_EXPERIMENTAL_CXX0X__
|
||||
value_type __x_copy = __x;
|
||||
#endif
|
||||
if (size_type(this->_M_impl._M_end_of_storage
|
||||
- this->_M_impl._M_finish) >= __n)
|
||||
{
|
||||
#ifndef __GXX_EXPERIMENTAL_CXX0X__
|
||||
value_type __x_copy = __x;
|
||||
#endif
|
||||
const size_type __elems_after = end() - __position;
|
||||
pointer __old_finish(this->_M_impl._M_finish);
|
||||
if (__elems_after > __n)
|
||||
|
@ -392,22 +397,24 @@ _GLIBCXX_BEGIN_NESTED_NAMESPACE(std, _GLIBCXX_STD_D)
|
|||
{
|
||||
const size_type __len =
|
||||
_M_check_len(__n, "vector::_M_fill_insert");
|
||||
const size_type __elems_before = __position - begin();
|
||||
pointer __new_start(this->_M_allocate(__len));
|
||||
pointer __new_finish(__new_start);
|
||||
try
|
||||
{
|
||||
// See _M_insert_aux above.
|
||||
std::__uninitialized_fill_n_a(__new_start + __elems_before,
|
||||
__n, __x,
|
||||
_M_get_Tp_allocator());
|
||||
__new_finish = 0;
|
||||
|
||||
__new_finish =
|
||||
std::__uninitialized_move_a(this->_M_impl._M_start,
|
||||
__position.base(),
|
||||
__new_start,
|
||||
_M_get_Tp_allocator());
|
||||
#ifdef __GXX_EXPERIMENTAL_CXX0X__
|
||||
std::__uninitialized_fill_n_a(__new_finish, __n, __x_copy,
|
||||
#else
|
||||
std::__uninitialized_fill_n_a(__new_finish, __n, __x,
|
||||
#endif
|
||||
_M_get_Tp_allocator());
|
||||
__new_finish += __n;
|
||||
|
||||
__new_finish =
|
||||
std::__uninitialized_move_a(__position.base(),
|
||||
this->_M_impl._M_finish,
|
||||
|
@ -416,8 +423,13 @@ _GLIBCXX_BEGIN_NESTED_NAMESPACE(std, _GLIBCXX_STD_D)
|
|||
}
|
||||
catch(...)
|
||||
{
|
||||
std::_Destroy(__new_start, __new_finish,
|
||||
_M_get_Tp_allocator());
|
||||
if (!__new_finish)
|
||||
std::_Destroy(__new_start + __elems_before,
|
||||
__new_start + __elems_before + __n,
|
||||
_M_get_Tp_allocator());
|
||||
else
|
||||
std::_Destroy(__new_start, __new_finish,
|
||||
_M_get_Tp_allocator());
|
||||
_M_deallocate(__new_start, __len);
|
||||
__throw_exception_again;
|
||||
}
|
||||
|
|
|
@ -1,6 +1,6 @@
|
|||
// { dg-options "-std=gnu++0x" }
|
||||
|
||||
// Copyright (C) 2005, 2007 Free Software Foundation, Inc.
|
||||
// Copyright (C) 2005, 2006, 2007, 2008 Free Software Foundation, Inc.
|
||||
//
|
||||
// This file is part of the GNU ISO C++ Library. This library is free
|
||||
// software; you can redistribute it and/or modify it under the
|
||||
|
@ -104,11 +104,11 @@ test04()
|
|||
std::vector<copycounter> a(10, c);
|
||||
copycounter::copycount = 0;
|
||||
a.insert(a.begin(), 20, c);
|
||||
VERIFY(copycounter::copycount == 20 + 1);
|
||||
VERIFY(copycounter::copycount == 20);
|
||||
a.insert(a.end(), 50, c);
|
||||
VERIFY(copycounter::copycount == 70 + 2);
|
||||
VERIFY(copycounter::copycount == 70);
|
||||
a.insert(a.begin() + 50, 100, c);
|
||||
VERIFY(copycounter::copycount == 170 + 3);
|
||||
VERIFY(copycounter::copycount == 170);
|
||||
}
|
||||
|
||||
// Test vector::insert(iterator, count, value) makes no unneeded copies
|
||||
|
|
|
@ -1,6 +1,6 @@
|
|||
// { dg-options "-std=gnu++0x" }
|
||||
|
||||
// Copyright (C) 2005, 2006, 2007 Free Software Foundation, Inc.
|
||||
// Copyright (C) 2005, 2006, 2007, 2008 Free Software Foundation, Inc.
|
||||
//
|
||||
// This file is part of the GNU ISO C++ Library. This library is free
|
||||
// software; you can redistribute it and/or modify it under the
|
||||
|
@ -51,28 +51,28 @@ test01()
|
|||
a.resize(99);
|
||||
a.resize(100);
|
||||
#ifndef _GLIBCXX_DEBUG
|
||||
VERIFY( copycounter::copycount == 100 + 4 );
|
||||
VERIFY( copycounter::copycount == 100 + 1 );
|
||||
#else
|
||||
VERIFY( copycounter::copycount == 100 + 4 + 4 );
|
||||
VERIFY( copycounter::copycount == 100 + 1 + 4 );
|
||||
#endif
|
||||
a.resize(99);
|
||||
a.resize(0);
|
||||
#ifndef _GLIBCXX_DEBUG
|
||||
VERIFY( copycounter::copycount == 100 + 4 );
|
||||
VERIFY( copycounter::copycount == 100 + 1 );
|
||||
#else
|
||||
VERIFY( copycounter::copycount == 100 + 4 + 6 );
|
||||
VERIFY( copycounter::copycount == 100 + 1 + 6 );
|
||||
#endif
|
||||
a.resize(100);
|
||||
#ifndef _GLIBCXX_DEBUG
|
||||
VERIFY( copycounter::copycount == 200 + 5 );
|
||||
VERIFY( copycounter::copycount == 200 + 2 );
|
||||
#else
|
||||
VERIFY( copycounter::copycount == 200 + 5 + 7 );
|
||||
VERIFY( copycounter::copycount == 200 + 2 + 7 );
|
||||
#endif
|
||||
a.clear();
|
||||
#ifndef _GLIBCXX_DEBUG
|
||||
VERIFY( copycounter::copycount == 200 + 5 );
|
||||
VERIFY( copycounter::copycount == 200 + 2 );
|
||||
#else
|
||||
VERIFY( copycounter::copycount == 200 + 5 + 7 );
|
||||
VERIFY( copycounter::copycount == 200 + 2 + 7 );
|
||||
#endif
|
||||
}
|
||||
|
||||
|
|
Loading…
Reference in New Issue