https://gcc.gnu.org/bugzilla/show_bug.cgi?id=78346
Bug ID: 78346
Summary: std::search with binary comparison predicate uses
invalid reference
Product: gcc
Version: unknown
Status: UNCONFIRMED
Severity: normal
Priority: P3
Component: libstdc++
Assignee: unassigned at gcc dot gnu.org
Reporter: reagentoo at gmail dot com
Target Milestone: ---
When using std::search with binary comparison predicate, reference obtained
from iterator outlives iterator itself
which violates part 24.2.1 [iterator.requirements.general] of C++ standard:
10. Destruction of an iterator may invalidate pointers and references
previously obtained from that iterator.
The iterator is being dereferenced when converting binary predicate to unary
for later use in std::find_if:
template<typename _ForwardIterator1, typename _ForwardIterator2,
typename _BinaryPredicate>
_ForwardIterator1
__search(_ForwardIterator1 __first1, _ForwardIterator1 __last1,
_ForwardIterator2 __first2, _ForwardIterator2 __last2,
_BinaryPredicate __predicate)
{
...
__first1 =
std::__find_if(__first1, __last1,
__gnu_cxx::__ops::__iter_comp_iter(__predicate, __first2));
In this expression __first2 is passed to a _Iter_equals_iter wrapper (from
bits/predefined_ops.h):
template<typename _Iterator1>
struct _Iter_equals_iter
{
typename std::iterator_traits<_Iterator1>::reference _M_ref; <-- reference
obtained from iterator
_Iter_equals_iter(_Iterator1 __it1)
: _M_ref(*__it1)
{ }
template<typename _Iterator2>
bool
operator()(_Iterator2 __it2)
{ return *__it2 == _M_ref; }
};
Since _Iterator1 __it1 is passed to constructor by value, _M_ref can become
invalid after iterator leaves the scope;
This behavior can be observed when using std::search with
boost::filesystem::path, since
boost::filesystem::path::iterator::dereference returns reference to a local
member:
http://melpon.org/wandbox/permlink/58aIbfJWeGgMKMdF
As a proposed solution, _Iter_equals_iter might store copy of iterator rather
than dereferenced
value.