[ https://issues.apache.org/jira/browse/STDCXX-618?page=com.atlassian.jira.plugin.system.issuetabpanels:all-tabpanel ]
Travis Vitek updated STDCXX-618: -------------------------------- Description: While investigating purify errors in 21.string.append.cpp, I ran into bunch FMR failures [this same failure occurs in other tests also]. They point to a legitimate bug in basic_string::replace() and possibly others like vector::insert(). I'm not really sure what the best approach for fixing this is because the issue itself is a little weird. There is also the issue of exception safety which makes it a little more interesting. #include <cassert> #include <string> #include <vector> template <class _IteratorT> struct dumb_input_iterator { typedef typename _IteratorT::value_type value_type; typedef typename _IteratorT::difference_type difference_type; typedef typename _IteratorT::pointer pointer; typedef typename _IteratorT::reference reference; typedef std::input_iterator_tag iterator_category; dumb_input_iterator (const _IteratorT &__rhs) : _C_iter (__rhs) {} reference operator* () const { return _C_iter.operator*(); } pointer operator-> () const { return _C_iter.operator->(); } dumb_input_iterator& operator++ () { return _C_iter.operator++(), *this; } dumb_input_iterator operator++ (int) { dumb_input_iterator __tmp(*this); _C_iter.operator++(); return __tmp; } bool operator== (const dumb_input_iterator &__rhs) const { return _C_iter == __rhs._C_iter; } bool operator!= (const dumb_input_iterator &__rhs) const { return !(_C_iter == __rhs._C_iter); } private: _IteratorT _C_iter; }; int main() { // i'm not exactly sure why you'd do this, but the following code // creates input iterators on top of bidirectional iterators. when // passing an input iterator to these [and possibly other] methods // it is assumed that the iterator does not refer to elements inside // the container, which is wrong. size_t n; typedef std::string string; string s(16, 'a'); // loop in an attempt to ensure internal buffer reallocation for (n = 0; n < 8; ++n) { size_t i = s.size (); const dumb_input_iterator<string::iterator> db (s.begin ()); const dumb_input_iterator<string::iterator> de (s.end ()); s.append (db, de); // s.append (s.begin (), s.end ()); // works as expected for (; i < s.size (); ++i) assert (s[i] == 'a'); } typedef std::vector<int> vector; vector v(16, 1); // loop in an attempt to ensure internal buffer reallocation for (n = 0; n < 8; ++n) { size_t i = v.size (); const dumb_input_iterator<vector::iterator> db (v.begin ()); const dumb_input_iterator<vector::iterator> de (v.end ()); v.insert (v.end (), db, de); // v.insert (v.end (), v.begin (), v.end ()); // works as expected for (; i < v.size (); ++i) assert (v[i] == 1); } return 0; } was: While investigating purify errors in 21.string.append.cpp, I ran into bunch FMR failures. They point to a legitimate bug in basic_string::replace() and possibly others like vector::insert(). I'm not really sure what the best approach for fixing this is because the issue itself is a little weird. There is also the issue of exception safety which makes it a little more interesting. #include <cassert> #include <string> #include <vector> template <class _IteratorT> struct dumb_input_iterator { typedef typename _IteratorT::value_type value_type; typedef typename _IteratorT::difference_type difference_type; typedef typename _IteratorT::pointer pointer; typedef typename _IteratorT::reference reference; typedef std::input_iterator_tag iterator_category; dumb_input_iterator (const _IteratorT &__rhs) : _C_iter (__rhs) {} reference operator* () const { return _C_iter.operator*(); } pointer operator-> () const { return _C_iter.operator->(); } dumb_input_iterator& operator++ () { return _C_iter.operator++(), *this; } dumb_input_iterator operator++ (int) { dumb_input_iterator __tmp(*this); _C_iter.operator++(); return __tmp; } bool operator== (const dumb_input_iterator &__rhs) const { return _C_iter == __rhs._C_iter; } bool operator!= (const dumb_input_iterator &__rhs) const { return !(_C_iter == __rhs._C_iter); } private: _IteratorT _C_iter; }; int main() { // i'm not exactly sure why you'd do this, but the following code // creates input iterators on top of bidirectional iterators. when // passing an input iterator to these [and possibly other] methods // it is assumed that the iterator does not refer to elements inside // the container, which is wrong. size_t n; typedef std::string string; string s(16, 'a'); // loop in an attempt to ensure internal buffer reallocation for (n = 0; n < 8; ++n) { size_t i = s.size (); const dumb_input_iterator<string::iterator> db (s.begin ()); const dumb_input_iterator<string::iterator> de (s.end ()); s.append (db, de); // s.append (s.begin (), s.end ()); // works as expected for (; i < s.size (); ++i) assert (s[i] == 'a'); } typedef std::vector<int> vector; vector v(16, 1); // loop in an attempt to ensure internal buffer reallocation for (n = 0; n < 8; ++n) { size_t i = v.size (); const dumb_input_iterator<vector::iterator> db (v.begin ()); const dumb_input_iterator<vector::iterator> de (v.end ()); v.insert (v.end (), db, de); // v.insert (v.end (), v.begin (), v.end ()); // works as expected for (; i < v.size (); ++i) assert (v[i] == 1); } return 0; } Summary: purify reports free memory read in 21.string.append test (was: purify free memory read in 21.string.append.cpp) > purify reports free memory read in 21.string.append test > -------------------------------------------------------- > > Key: STDCXX-618 > URL: https://issues.apache.org/jira/browse/STDCXX-618 > Project: C++ Standard Library > Issue Type: Bug > Components: 21. Strings > Affects Versions: 4.2 > Reporter: Travis Vitek > Priority: Minor > Fix For: 4.2.1 > > Attachments: 21.string.append.log > > > While investigating purify errors in 21.string.append.cpp, I ran into bunch > FMR failures [this same failure occurs in other tests also]. They point to a > legitimate bug in basic_string::replace() and possibly others like > vector::insert(). I'm not really sure what the best approach for fixing this > is because the issue itself is a little weird. There is also the issue of > exception safety which makes it a little more interesting. > #include <cassert> > #include <string> > #include <vector> > template <class _IteratorT> > struct dumb_input_iterator > { > typedef typename _IteratorT::value_type value_type; > typedef typename _IteratorT::difference_type difference_type; > typedef typename _IteratorT::pointer pointer; > typedef typename _IteratorT::reference reference; > typedef std::input_iterator_tag iterator_category; > dumb_input_iterator (const _IteratorT &__rhs) > : _C_iter (__rhs) {} > reference operator* () const { > return _C_iter.operator*(); > } > pointer operator-> () const { > return _C_iter.operator->(); > } > dumb_input_iterator& operator++ () { > return _C_iter.operator++(), *this; > } > dumb_input_iterator operator++ (int) { > dumb_input_iterator __tmp(*this); > _C_iter.operator++(); > return __tmp; > } > bool > operator== (const dumb_input_iterator &__rhs) const { > return _C_iter == __rhs._C_iter; > } > bool > operator!= (const dumb_input_iterator &__rhs) const { > return !(_C_iter == __rhs._C_iter); > } > private: > _IteratorT _C_iter; > }; > int main() > { > // i'm not exactly sure why you'd do this, but the following code > // creates input iterators on top of bidirectional iterators. when > // passing an input iterator to these [and possibly other] methods > // it is assumed that the iterator does not refer to elements inside > // the container, which is wrong. > size_t n; > typedef std::string string; > string s(16, 'a'); > // loop in an attempt to ensure internal buffer reallocation > for (n = 0; n < 8; ++n) > { > size_t i = s.size (); > const dumb_input_iterator<string::iterator> db (s.begin ()); > const dumb_input_iterator<string::iterator> de (s.end ()); > s.append (db, de); > // s.append (s.begin (), s.end ()); // works as expected > for (; i < s.size (); ++i) > assert (s[i] == 'a'); > } > typedef std::vector<int> vector; > vector v(16, 1); > // loop in an attempt to ensure internal buffer reallocation > for (n = 0; n < 8; ++n) > { > size_t i = v.size (); > const dumb_input_iterator<vector::iterator> db (v.begin ()); > const dumb_input_iterator<vector::iterator> de (v.end ()); > v.insert (v.end (), db, de); > // v.insert (v.end (), v.begin (), v.end ()); // works as expected > for (; i < v.size (); ++i) > assert (v[i] == 1); > } > return 0; > } -- This message is automatically generated by JIRA. - You can reply to this email to add a comment to the issue online.