Weird crasher with std::remove, std::erase

Discussion in 'C++' started by groups@barnholt.net, Mar 24, 2007.

  1. Guest

    This small piece of code is troubling me.. is there anything wrong
    with it??
    After calling this method the contents ot the input vector are
    completely screwed..
    (CCountedCIG_CountZero() applies only to a few elements in the vector)

    void UElementVector::ClearZeroCountElements(vector<CCountedCIG*>
    &ioItemVec)
    {
    vector<CCountedCIG*>::iterator new_end = remove_if(ioItemVec.begin(),
    ioItemVec.end(), CCountedCIG_CountZero());

    for (vector<CCountedCIG*>::iterator it = new_end; it !=
    ioItemVec.end(); it++)
    {
    delete *it;
    *it = NULL;
    }

    ioItemVec.erase(new_end, ioItemVec.end());
    }


    Any help is much apreciated!

    regards,
    jan
     
    , Mar 24, 2007
    #1
    1. Advertising

  2. In article <>,
    wrote:

    > This small piece of code is troubling me.. is there anything wrong
    > with it??
    > After calling this method the contents ot the input vector are
    > completely screwed..
    > (CCountedCIG_CountZero() applies only to a few elements in the vector)
    >
    > void UElementVector::ClearZeroCountElements(vector<CCountedCIG*>
    > &ioItemVec)
    > {
    > vector<CCountedCIG*>::iterator new_end = remove_if(ioItemVec.begin(),
    > ioItemVec.end(), CCountedCIG_CountZero());
    >
    > for (vector<CCountedCIG*>::iterator it = new_end; it !=
    > ioItemVec.end(); it++)
    > {
    > delete *it;
    > *it = NULL;
    > }
    >
    > ioItemVec.erase(new_end, ioItemVec.end());
    > }


    <nod> The problem is that remove_if works just by overwriting elements
    that no longer belong in the sequence. It doesn't swap them to the end.
    What is most likely happening is that you are overwriting the pointers
    you want to delete. And then you are deleting copies of the pointers
    you want to keep. A subsequent dereference leads to a crash.

    You could do a two-pass operation where the first pass did:

    1. Check if you want to delete, and if so:
    2. delete
    3. null pointer

    transform could possibly be employed for the first pass.

    And then the second pass could call remove (if null pointer).

    Or you could write your own algorithm which combines these passes into a
    single pass.

    -Howard
     
    Howard Hinnant, Mar 24, 2007
    #2
    1. Advertising

  3. Guest

    On Mar 24, 9:41 pm, Howard Hinnant <> wrote:

    > <nod> The problem is that remove_if works just by overwriting elements
    > that no longer belong in the sequence. It doesn't swap them to the end.
    > What is most likely happening is that you are overwriting the pointers
    > you want to delete. And then you are deleting copies of the pointers
    > you want to keep. A subsequent dereference leads to a crash.



    D'oh! Thanks for the hint -- carefully re-reading the docs it's all
    there..

    | Remove_if removes from the range [first, last) every element x such
    that pred(x) is true.
    | That is, remove_if returns an iterator new_last such that the range
    [first, new_last)
    | contains no elements for which pred is true. [1] The iterators in
    the range [new_last, last)
    | are all still dereferenceable, but the elements that they point to
    are unspecified.
    | ..


    cheers,
    jan
     
    , Mar 25, 2007
    #3
  4. terminator Guest

    On Mar 25, 11:44 am, wrote:
    > On Mar 24, 9:41 pm, Howard Hinnant <> wrote:
    >
    > > <nod> The problem is that remove_if works just by overwriting elements
    > > that no longer belong in the sequence. It doesn't swap them to the end.
    > > What is most likely happening is that you are overwriting the pointers
    > > you want to delete. And then you are deleting copies of the pointers
    > > you want to keep. A subsequent dereference leads to a crash.

    >
    > D'oh! Thanks for the hint -- carefully re-reading the docs it's all
    > there..
    >
    > | Remove_if removes from the range [first, last) every element x such
    > that pred(x) is true.
    > | That is, remove_if returns an iterator new_last such that the range
    > [first, new_last)
    > | contains no elements for which pred is true. [1] The iterators in
    > the range [new_last, last)
    > | are all still dereferenceable, but the elements that they point to
    > are unspecified.
    > | ..
    >
    > cheers,
    > jan


    This behavior surprises me.I have read the source code for remove
    family but I do not understand how they can be useful!!!????
    remembering that they won`t work with map whose elements are none-
    assignable 'pair's.
     
    terminator, Mar 25, 2007
    #4
    1. Advertising

Want to reply to this thread or ask your own question?

It takes just 2 minutes to sign up (and it's free!). Just click the sign up button to choose a username and then you can ask your own questions on the forum.
Similar Threads
  1. John Smith
    Replies:
    7
    Views:
    420
    John Smith
    Dec 25, 2004
  2. Nan Li
    Replies:
    2
    Views:
    1,068
    Andrew Koenig
    Nov 8, 2005
  3. erase vs. erase

    , Mar 25, 2006, in forum: C++
    Replies:
    7
    Views:
    369
    Pete Becker
    Mar 30, 2006
  4. Wing

    erase-remove usage

    Wing, Nov 4, 2006, in forum: C++
    Replies:
    3
    Views:
    330
    Ian Collins
    Nov 4, 2006
  5. Öö Tiib
    Replies:
    0
    Views:
    737
    Öö Tiib
    Jun 16, 2010
Loading...

Share This Page