Archived

This topic is now archived and is closed to further replies.

Oxyd

std::list.end () iterator decreasing when nothing removed from list?

Recommended Posts

std::list <Gc *>::iterator i = garbage.begin ();

while (i != garbage.end ()) {
	delete *i;
	++i;
}
At the moment of execution, there''s only one element in the list. When I run it, in the first iteration of the loop, everything goes OK, but in the second one, my program crash. I''ve debugged out, that it is because at the moment of delete *i; statement the value of garbage.end () iterator is decreased (to the garbage.begin (), because there''s only one element) and the i increased, thus it causes a crash. But why is the garbage.end () decreased when freeing memory pointed to by the iterator? Is it normal? Oxyd --- - Unreadable code is code written on a piece of paper, but not the one, in which the programmer is using a space in the place you don''t. - Real programmers aren''t afraid of goto

Share this post


Link to post
Share on other sites
quote:
''ve debugged out, that it is because at the moment of delete *i; statement the value of garbage.end () iterator is decreased (to the garbage.begin (), because there''s only one element) and the i increased, thus it causes a crash.

That''s not correct. Unless you''re doing truly bizarre things (holding a reference to the list itself as part of the list) deleting the pointed-to member cannot affect the list.
What crash is it causing? What does the stack trace say?


"Sneftel is correct, if rather vulgar." --Flarelocke

Share this post


Link to post
Share on other sites
Well - it is causing that the it is increased and end () decreased. Thus it is one step ABOVE end, thus != end () == true, thus it continues on second iteration, and it is pointing outside the list at the moment.

Uhh.. stack trace ()? Nothing especial I would say... Call the destructor for the object, my user-defined delete operator, iterator++ operator, and again the list.end () and != operator... (Or did you mean it different way? I only hope you meant this ).

Oxyd.

Share this post


Link to post
Share on other sites
look, you are NOT affecting the "list", you are deleting the thing pointed to by the iterator, which invalidates THAT iterator, and EVERY ITERATOR TO THAT ITEM ...

you must ADVANCE the iterator first, then delete the item through a copy, just like in any other linked list code you would have written for C .. like:


std::list <Gc *>::iterator i = garbage.begin ();
while (i != garbage.end ())
{
std::list <Gc *>::iterator temp = i; // copy current iterator

++i; // advance main iterator

delete *temp; // delete original argument to block using temp

}

Share this post


Link to post
Share on other sites
It''s not even invalidating the iterator. It''s deleting the pointer inside the list node, not removing the node from the list.


std::list<Gc*>::iterator it = garbage.begin();
for(; it!=garbage.end(); ++it)
delete *it;
garbage.clear();

Share this post


Link to post
Share on other sites
quote:
Original post by Oxyd
Uhh.. stack trace ()? Nothing especial I would say... Call the destructor for the object, my user-defined delete operator, iterator++ operator, and again the list.end () and != operator... (Or did you mean it different way? I only hope you meant this ).

I meant copy and paste the stack trace as it is displayed in the debugger at the time of the error.


"Sneftel is correct, if rather vulgar." --Flarelocke

Share this post


Link to post
Share on other sites
so Magmai hinted at the whole solution .. if you think ..

you are not REMOVING the item from your garbage list .. you are just deleting the pointed to item from the heap ...

FIRST ... if you set the *it to 0(NULL) right after you delete it, then it will stop crashing ... cause then each pass through the loop you''d just be calling delete on 0 a bunch of extra times

SECOND ... then - you need to remove it from your list (which is where my post comes in), you need to actually remove the items from the container list ... either with erase() as you work ... or if you are inheirantly deleting every object in the list, then you can just use something like clear() at the end of the loop to do it all at once.

THIRD ... if you are remove the items like you should (in SECOND item above), then you don''t really need to waste the time to do FIRST above ... cause it won''t matter - BUT, now you have seen a case in the real world, where not setting a deleted pointer to null, crashes your program. I''m just saying, ALWAYS set a deleted pointer to 0, first ... THEN optimize the assignment away if you know it cannot matter.

The only case where I don''t assign pointers to 0 after delete is when the lines to delete and assign are back-to-back, and when the object is a member, and I''m in a desructor (you never need to set top level member pointers to 0 in a destructor, cause they cannot legally be accessed after the destructor is called anyway.

Share this post


Link to post
Share on other sites