re PR libstdc++/48750 (for_each_template_random_access_ed has unbalanced new/delete[])

2011-05-03  Paolo Carlini  <paolo.carlini@oracle.com>

	PR libstdc++/48750
	* include/parallel/multiway_merge.h: Run _ValueType destructors.
	* include/parallel/multiway_mergesort.h: Likewise.
	* include/parallel/quicksort.h: Likewise.
	* include/parallel/random_shuffle.h: Likewise.
	* include/parallel/partial_sum.h: Likewise.
	* include/parallel/losertree.h: Run destructors; minor tweaks.
	* include/parallel/par_loop.h: Run destructors, fix memory
	allocations and deallocations.
	* testsuite/26_numerics/accumulate/48750.cc: New.

	* testsuite/ext/profile/mutex_extensions_neg.cc: Do not run in
	parallel-mode to avoid spurious multiple errors.

From-SVN: r173309
This commit is contained in:
Paolo Carlini 2011-05-03 14:20:45 +00:00 committed by Paolo Carlini
parent 7071d0648c
commit 0ecca7a6a6
10 changed files with 166 additions and 35 deletions

View File

@ -1,3 +1,19 @@
2011-05-03 Paolo Carlini <paolo.carlini@oracle.com>
PR libstdc++/48750
* include/parallel/multiway_merge.h: Run _ValueType destructors.
* include/parallel/multiway_mergesort.h: Likewise.
* include/parallel/quicksort.h: Likewise.
* include/parallel/random_shuffle.h: Likewise.
* include/parallel/partial_sum.h: Likewise.
* include/parallel/losertree.h: Run destructors; minor tweaks.
* include/parallel/par_loop.h: Run destructors, fix memory
allocations and deallocations.
* testsuite/26_numerics/accumulate/48750.cc: New.
* testsuite/ext/profile/mutex_extensions_neg.cc: Do not run in
parallel-mode to avoid spurious multiple errors.
2011-05-03 Jonathan Wakely <jwakely.gcc@gmail.com>
* include/std/functional (bind): Remove from overload set when first

View File

@ -1,6 +1,6 @@
// -*- C++ -*-
// Copyright (C) 2007, 2008, 2009 Free Software Foundation, Inc.
// Copyright (C) 2007, 2008, 2009, 2010, 2011 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 terms
@ -116,7 +116,11 @@ namespace __gnu_parallel
* @brief The destructor.
*/
~_LoserTreeBase()
{ ::operator delete(_M_losers); }
{
for (unsigned int __i = 0; __i < (2 * _M_k); ++__i)
_M_losers[__i].~_Loser();
::operator delete(_M_losers);
}
/**
* @brief Initializes the sequence "_M_source" with the element "__key".
@ -131,15 +135,15 @@ namespace __gnu_parallel
{
unsigned int __pos = _M_k + __source;
if(_M_first_insert)
if (_M_first_insert)
{
// Construct all keys, so we can easily deconstruct them.
// Construct all keys, so we can easily destruct them.
for (unsigned int __i = 0; __i < (2 * _M_k); ++__i)
new(&(_M_losers[__i]._M_key)) _Tp(__key);
::new(&(_M_losers[__i]._M_key)) _Tp(__key);
_M_first_insert = false;
}
else
new(&(_M_losers[__pos]._M_key)) _Tp(__key);
_M_losers[__pos]._M_key = __key;
_M_losers[__pos]._M_sup = __sup;
_M_losers[__pos]._M_source = __source;
@ -379,7 +383,7 @@ namespace __gnu_parallel
}
~_LoserTreePointerBase()
{ ::operator delete[](_M_losers); }
{ delete[] _M_losers; }
int __get_min_source()
{ return _M_losers[0]._M_source; }
@ -577,7 +581,7 @@ namespace __gnu_parallel
_Compare _M_comp;
public:
_LoserTreeUnguardedBase(unsigned int __k, const _Tp __sentinel,
_LoserTreeUnguardedBase(unsigned int __k, const _Tp& __sentinel,
_Compare __comp = std::less<_Tp>())
: _M_comp(__comp)
{
@ -590,15 +594,24 @@ namespace __gnu_parallel
_M_losers = static_cast<_Loser*>(::operator new(2 * _M_k
* sizeof(_Loser)));
for (unsigned int __i = 0; __i < _M_k; ++__i)
{
::new(&(_M_losers[__i]._M_key)) _Tp(__sentinel);
_M_losers[__i]._M_source = -1;
}
for (unsigned int __i = _M_k + _M_ik - 1; __i < (2 * _M_k); ++__i)
{
_M_losers[__i]._M_key = __sentinel;
::new(&(_M_losers[__i]._M_key)) _Tp(__sentinel);
_M_losers[__i]._M_source = -1;
}
}
~_LoserTreeUnguardedBase()
{ ::operator delete(_M_losers); }
{
for (unsigned int __i = 0; __i < (2 * _M_k); ++__i)
_M_losers[__i].~_Loser();
::operator delete(_M_losers);
}
int
__get_min_source()
@ -615,7 +628,7 @@ namespace __gnu_parallel
{
unsigned int __pos = _M_k + __source;
new(&(_M_losers[__pos]._M_key)) _Tp(__key);
::new(&(_M_losers[__pos]._M_key)) _Tp(__key);
_M_losers[__pos]._M_source = __source;
}
};
@ -634,7 +647,7 @@ namespace __gnu_parallel
using _Base::_M_losers;
public:
_LoserTreeUnguarded(unsigned int __k, const _Tp __sentinel,
_LoserTreeUnguarded(unsigned int __k, const _Tp& __sentinel,
_Compare __comp = std::less<_Tp>())
: _Base::_LoserTreeUnguardedBase(__k, __sentinel, __comp)
{ }
@ -721,7 +734,7 @@ namespace __gnu_parallel
using _Base::_M_losers;
public:
_LoserTreeUnguarded(unsigned int __k, const _Tp __sentinel,
_LoserTreeUnguarded(unsigned int __k, const _Tp& __sentinel,
_Compare __comp = std::less<_Tp>())
: _Base::_LoserTreeUnguardedBase(__k, __sentinel, __comp)
{ }

View File

@ -1045,11 +1045,12 @@ namespace __gnu_parallel
_ValueType;
// __k sequences.
_SeqNumber __k = static_cast<_SeqNumber>(__seqs_end - __seqs_begin);
const _SeqNumber __k
= static_cast<_SeqNumber>(__seqs_end - __seqs_begin);
_ThreadIndex __num_threads = omp_get_num_threads();
const _ThreadIndex __num_threads = omp_get_num_threads();
_DifferenceType __num_samples =
const _DifferenceType __num_samples =
__gnu_parallel::_Settings::get().merge_oversampling * __num_threads;
_ValueType* __samples = static_cast<_ValueType*>
@ -1096,6 +1097,10 @@ namespace __gnu_parallel
__pieces[__slab][__seq].second =
_GLIBCXX_PARALLEL_LENGTH(__seqs_begin[__seq]);
}
for (_SeqNumber __s = 0; __s < __k; ++__s)
for (_DifferenceType __i = 0; __i < __num_samples; ++__i)
__samples[__s * __num_samples + __i].~_ValueType();
::operator delete(__samples);
}

View File

@ -378,6 +378,8 @@ namespace __gnu_parallel
# pragma omp barrier
for (_DifferenceType __i = 0; __i < __length_local; ++__i)
__sd->_M_temporary[__iam][__i].~_ValueType();
::operator delete(__sd->_M_temporary[__iam]);
}
@ -413,6 +415,7 @@ namespace __gnu_parallel
// shared variables
_PMWMSSortingData<_RAIter> __sd;
_DifferenceType* __starts;
_DifferenceType __size;
# pragma omp parallel num_threads(__num_threads)
{
@ -427,7 +430,7 @@ namespace __gnu_parallel
if (!__exact)
{
_DifferenceType __size =
__size =
(_Settings::get().sort_mwms_oversampling * __num_threads - 1)
* __num_threads;
__sd._M_samples = static_cast<_ValueType*>
@ -463,7 +466,11 @@ namespace __gnu_parallel
delete[] __sd._M_temporary;
if (!__exact)
{
for (_DifferenceType __i = 0; __i < __size; ++__i)
__sd._M_samples[__i].~_ValueType();
::operator delete(__sd._M_samples);
}
delete[] __sd._M_offsets;
delete[] __sd._M_pieces;

View File

@ -91,8 +91,7 @@ namespace __gnu_parallel
_ThreadIndex __iam = omp_get_thread_num();
// Neutral element.
_Result* __reduct = static_cast<_Result*>
(::operator new(sizeof(_Result)));
_Result* __reduct;
_DifferenceType
__start = __equally_split_point(__length, __num_threads, __iam),
@ -100,7 +99,7 @@ namespace __gnu_parallel
if (__start < __stop)
{
new(__reduct) _Result(__f(__o, __begin + __start));
__reduct = new _Result(__f(__o, __begin + __start));
++__start;
__constructed[__iam] = true;
}
@ -110,18 +109,26 @@ namespace __gnu_parallel
for (; __start < __stop; ++__start)
*__reduct = __r(*__reduct, __f(__o, __begin + __start));
__thread_results[__iam] = *__reduct;
if (__constructed[__iam])
{
::new(&__thread_results[__iam]) _Result(*__reduct);
delete __reduct;
}
} //parallel
for (_ThreadIndex __i = 0; __i < __num_threads; ++__i)
if (__constructed[__i])
{
__output = __r(__output, __thread_results[__i]);
__thread_results[__i].~_Result();
}
// Points to last element processed (needed as return value for
// some algorithms like transform).
__f._M_finish_iterator = __begin + __length;
delete[] __thread_results;
::operator delete(__thread_results);
delete[] __constructed;
return __o;

View File

@ -184,7 +184,10 @@ namespace __gnu_parallel
__bin_op, __sums[__iam]);
} //parallel
for (_ThreadIndex __i = 0; __i < __num_threads; ++__i)
__sums[__i].~_ValueType();
::operator delete(__sums);
delete[] __borders;
return __result + __n;

View File

@ -1,6 +1,6 @@
// -*- C++ -*-
// Copyright (C) 2007, 2008, 2009, 2010 Free Software Foundation, Inc.
// Copyright (C) 2007, 2008, 2009, 2010, 2011 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 terms
@ -82,6 +82,8 @@ namespace __gnu_parallel
_DifferenceType __split = __parallel_partition(__begin, __end,
__pred, __num_threads);
for (_DifferenceType __s = 0; __s < __num_samples; ++__s)
__samples[__s].~_ValueType();
::operator delete(__samples);
return __split;

View File

@ -1,6 +1,6 @@
// -*- C++ -*-
// Copyright (C) 2007, 2008, 2009, 2010 Free Software Foundation, Inc.
// Copyright (C) 2007, 2008, 2009, 2010, 2011 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 terms
@ -227,7 +227,7 @@ namespace __gnu_parallel
(__sd->_M_temporaries[__iam]
+ (__b == __d->_M_bins_begin
? 0 : __sd->_M_dist[__b][__d->_M_num_threads])),
* __end = (__sd->_M_temporaries[__iam]
*__end = (__sd->_M_temporaries[__iam]
+ __sd->_M_dist[__b + 1][__d->_M_num_threads]);
__sequential_random_shuffle(__begin, __end, __rng);
@ -236,6 +236,8 @@ namespace __gnu_parallel
? 0 : __sd->_M_dist[__b][__d->_M_num_threads]));
}
for (_SequenceIndex __i = 0; __i < __offset; ++__i)
__sd->_M_temporaries[__iam][__i].~_ValueType();
::operator delete(__sd->_M_temporaries[__iam]);
}
@ -501,6 +503,9 @@ namespace __gnu_parallel
delete[] __dist0;
delete[] __dist1;
delete[] __oracles;
for (_DifferenceType __i = 0; __i < __n; ++__i)
__target[__i].~_ValueType();
::operator delete(__target);
}
else

View File

@ -0,0 +1,70 @@
// Copyright (C) 2011 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
// terms of the GNU General Public License as published by the
// Free Software Foundation; either version 3, or (at your option)
// any later version.
// This library is distributed in the hope that it will be useful,
// but WITHOUT ANY WARRANTY; without even the implied warranty of
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
// GNU General Public License for more details.
// You should have received a copy of the GNU General Public License along
// with this library; see the file COPYING3. If not see
// <http://www.gnu.org/licenses/>.
#include <vector>
#include <numeric>
class NaturalParameters
{
public:
NaturalParameters()
: m_data(2)
{ }
std::vector<double>::const_iterator
begin() const
{ return m_data.begin(); }
std::vector<double>::const_iterator
end() const
{ return m_data.begin(); }
NaturalParameters&
operator+=(const NaturalParameters&)
{ return *this; }
private:
std::vector<double> m_data;
};
inline
NaturalParameters
operator+(const NaturalParameters& a, const NaturalParameters& b)
{
NaturalParameters tmp = a;
return tmp += b;
}
// libstdc++/48750
void test01()
{
// Used to fail in parallel-mode with a segfault.
for (std::size_t i = 0; i < 1000; ++i)
{
std::vector<NaturalParameters> ChildrenNP(1000);
NaturalParameters init;
NaturalParameters NP = std::accumulate(ChildrenNP.begin(),
ChildrenNP.end(), init);
}
}
int main()
{
test01();
return 0;
}

View File

@ -3,6 +3,9 @@
// -*- C++ -*-
// Otherwise we may get *multiple* errors.
#undef _GLIBCXX_PARALLEL
// Copyright (C) 2006, 2007, 2009, 2010, 2011 Free Software Foundation, Inc.
//
// This file is part of the GNU ISO C++ Library. This library is free