Issue Details (XML | Word | Printable)

Key: STDCXX-618
Type: Bug Bug
Status: Open Open
Priority: Minor Minor
Assignee: Unassigned
Reporter: Travis Vitek
Votes: 0
Watchers: 0
Operations

If you were logged in you would be able to see more operations.
C++ Standard Library

purify reports free memory read in 21.string.append test

Created: 24/Oct/07 10:53 PM   Updated: 11/Jul/09 12:00 AM
Return to search
Component/s: 21. Strings
Affects Version/s: 4.2.0
Fix Version/s: 4.2.2

Time Tracking:
Original Estimate: 4h
Original Estimate - 4h
Remaining Estimate: 4h
Remaining Estimate - 4h
Time Spent: Not Specified
Remaining Estimate - 4h

File Attachments:
  Size
Text File Licensed for inclusion in ASF works 21.string.append.log 2007-10-24 10:54 PM Travis Vitek 55 kB

Severity: Incorrect Behavior


 Description  « Hide
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;
}


 All   Comments   Work Log   Change History   Subversion Commits      Sort Order: Ascending order - Click to sort in descending order
Travis Vitek made changes - 24/Oct/07 10:54 PM
Field Original Value New Value
Attachment 21.string.append.log [ 12368330 ]
Travis Vitek made changes - 24/Oct/07 11:10 PM
Description 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;
}



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;
}



Summary purify free memory read in 21.string.append.cpp purify reports free memory read in 21.string.append test
Martin Sebor made changes - 21/Jan/08 06:33 PM
Remaining Estimate 4h [ 14400 ]
Original Estimate 4h [ 14400 ]
Martin Sebor made changes - 01/Feb/08 04:35 AM
Assignee Travis Vitek [ vitek ]
Martin Sebor made changes - 01/Feb/08 04:37 AM
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;
}



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.

{noformat}
#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;
}
{noformat}
Travis Vitek made changes - 23/Apr/08 08:39 PM
Fix Version/s 4.2.1 [ 12312690 ]
Fix Version/s 4.2.2 [ 12313096 ]
Travis Vitek made changes - 11/Jul/09 12:00 AM
Assignee Travis Vitek [ vitek ]